/*
 * Copyright (C) 2006 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;

import static android.Manifest.permission.ACCESS_MEDIA_LOCATION;
import static android.app.AppOpsManager.permissionToOp;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_ONE_SHOT;
import static android.content.ContentResolver.QUERY_ARG_SQL_SELECTION;
import static android.content.ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.database.Cursor.FIELD_TYPE_BLOB;
import static android.provider.CloudMediaProviderContract.EXTRA_ASYNC_CONTENT_PROVIDER;
import static android.provider.CloudMediaProviderContract.METHOD_GET_ASYNC_CONTENT_PROVIDER;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE;
import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
import static android.provider.MediaStore.Files.FileColumns._SPECIAL_FORMAT;
import static android.provider.MediaStore.Files.FileColumns._SPECIAL_FORMAT_NONE;
import static android.provider.MediaStore.MATCH_DEFAULT;
import static android.provider.MediaStore.MATCH_EXCLUDE;
import static android.provider.MediaStore.MATCH_INCLUDE;
import static android.provider.MediaStore.MATCH_ONLY;
import static android.provider.MediaStore.MY_UID;
import static android.provider.MediaStore.PER_USER_RANGE;
import static android.provider.MediaStore.QUERY_ARG_DEFER_SCAN;
import static android.provider.MediaStore.QUERY_ARG_MATCH_FAVORITE;
import static android.provider.MediaStore.QUERY_ARG_MATCH_PENDING;
import static android.provider.MediaStore.QUERY_ARG_MATCH_TRASHED;
import static android.provider.MediaStore.QUERY_ARG_REDACTED_URI;
import static android.provider.MediaStore.QUERY_ARG_RELATED_URI;
import static android.provider.MediaStore.VOLUME_EXTERNAL;
import static android.provider.MediaStore.getVolumeName;
import static android.system.OsConstants.F_GETFL;

import static com.android.providers.media.DatabaseHelper.EXTERNAL_DATABASE_NAME;
import static com.android.providers.media.DatabaseHelper.INTERNAL_DATABASE_NAME;
import static com.android.providers.media.LocalCallingIdentity.APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_ACCESS_MTP;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_INSTALL_PACKAGES;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_DELEGATOR;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_LEGACY_GRANTED;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_LEGACY_READ;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_LEGACY_WRITE;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_MANAGER;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_REDACTION_NEEDED;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SELF;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SHELL;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_IS_SYSTEM_GALLERY;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_AUDIO;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_IMAGES;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_READ_VIDEO;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_WRITE_AUDIO;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_WRITE_EXTERNAL_STORAGE;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_WRITE_IMAGES;
import static com.android.providers.media.LocalCallingIdentity.PERMISSION_WRITE_VIDEO;
import static com.android.providers.media.PickerUriResolver.getMediaUri;
import static com.android.providers.media.scan.MediaScanner.REASON_DEMAND;
import static com.android.providers.media.scan.MediaScanner.REASON_IDLE;
import static com.android.providers.media.util.DatabaseUtils.bindList;
import static com.android.providers.media.util.FileUtils.DEFAULT_FOLDER_NAMES;
import static com.android.providers.media.util.FileUtils.PATTERN_PENDING_FILEPATH_FOR_SQL;
import static com.android.providers.media.util.FileUtils.buildPrimaryVolumeFile;
import static com.android.providers.media.util.FileUtils.extractDisplayName;
import static com.android.providers.media.util.FileUtils.extractFileExtension;
import static com.android.providers.media.util.FileUtils.extractFileName;
import static com.android.providers.media.util.FileUtils.extractOwnerPackageNameFromRelativePath;
import static com.android.providers.media.util.FileUtils.extractPathOwnerPackageName;
import static com.android.providers.media.util.FileUtils.extractRelativePath;
import static com.android.providers.media.util.FileUtils.extractRelativePathWithDisplayName;
import static com.android.providers.media.util.FileUtils.extractTopLevelDir;
import static com.android.providers.media.util.FileUtils.extractVolumeName;
import static com.android.providers.media.util.FileUtils.extractVolumePath;
import static com.android.providers.media.util.FileUtils.fromFuseFile;
import static com.android.providers.media.util.FileUtils.getAbsoluteSanitizedPath;
import static com.android.providers.media.util.FileUtils.isCrossUserEnabled;
import static com.android.providers.media.util.FileUtils.isDataOrObbPath;
import static com.android.providers.media.util.FileUtils.isDataOrObbRelativePath;
import static com.android.providers.media.util.FileUtils.isDownload;
import static com.android.providers.media.util.FileUtils.isExternalMediaDirectory;
import static com.android.providers.media.util.FileUtils.isObbOrChildRelativePath;
import static com.android.providers.media.util.FileUtils.sanitizePath;
import static com.android.providers.media.util.FileUtils.toFuseFile;
import static com.android.providers.media.util.Logging.LOGV;
import static com.android.providers.media.util.Logging.TAG;
import static com.android.providers.media.util.SyntheticPathUtils.REDACTED_URI_ID_PREFIX;
import static com.android.providers.media.util.SyntheticPathUtils.REDACTED_URI_ID_SIZE;
import static com.android.providers.media.util.SyntheticPathUtils.createSparseFile;
import static com.android.providers.media.util.SyntheticPathUtils.extractSyntheticRelativePathSegements;
import static com.android.providers.media.util.SyntheticPathUtils.getRedactedRelativePath;
import static com.android.providers.media.util.SyntheticPathUtils.isPickerPath;
import static com.android.providers.media.util.SyntheticPathUtils.isRedactedPath;
import static com.android.providers.media.util.SyntheticPathUtils.isSyntheticPath;

import android.annotation.IntDef;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OnOpActiveChangedListener;
import android.app.AppOpsManager.OnOpChangedListener;
import android.app.DownloadManager;
import android.app.PendingIntent;
import android.app.RecoverableSecurityException;
import android.app.RemoteAction;
import android.app.admin.DevicePolicyManager;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.ContentProvider;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.UriMatcher;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon;
import android.icu.util.ULocale;
import android.media.ExifInterface;
import android.media.ThumbnailUtils;
import android.mtp.MtpConstants;
import android.net.Uri;
import android.os.Binder;
import android.os.Binder.ProxyTransactListener;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Environment;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.ParcelFileDescriptor.OnCloseListener;
import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.StorageManager.StorageVolumeCallback;
import android.os.storage.StorageVolume;
import android.preference.PreferenceManager;
import android.provider.AsyncContentProvider;
import android.provider.BaseColumns;
import android.provider.Column;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.OnPropertiesChangedListener;
import android.provider.DocumentsContract;
import android.provider.ExportedSince;
import android.provider.IAsyncContentProvider;
import android.provider.MediaStore;
import android.provider.MediaStore.Audio;
import android.provider.MediaStore.Audio.AudioColumns;
import android.provider.MediaStore.Audio.Playlists;
import android.provider.MediaStore.Downloads;
import android.provider.MediaStore.Files;
import android.provider.MediaStore.Files.FileColumns;
import android.provider.MediaStore.Images;
import android.provider.MediaStore.Images.ImageColumns;
import android.provider.MediaStore.MediaColumns;
import android.provider.MediaStore.Video;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.system.StructStat;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
import android.util.Size;
import android.util.SparseArray;
import android.webkit.MimeTypeMap;

import androidx.annotation.GuardedBy;
import androidx.annotation.Keep;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;

import com.android.modules.utils.BackgroundThread;
import com.android.modules.utils.build.SdkLevel;
import com.android.providers.media.DatabaseHelper.OnFilesChangeListener;
import com.android.providers.media.DatabaseHelper.OnLegacyMigrationListener;
import com.android.providers.media.dao.FileRow;
import com.android.providers.media.fuse.ExternalStorageServiceImpl;
import com.android.providers.media.fuse.FuseDaemon;
import com.android.providers.media.metrics.PulledMetrics;
import com.android.providers.media.photopicker.PickerDataLayer;
import com.android.providers.media.photopicker.PickerSyncController;
import com.android.providers.media.photopicker.data.ExternalDbFacade;
import com.android.providers.media.photopicker.data.PickerDbFacade;
import com.android.providers.media.playlist.Playlist;
import com.android.providers.media.scan.MediaScanner;
import com.android.providers.media.scan.ModernMediaScanner;
import com.android.providers.media.util.CachedSupplier;
import com.android.providers.media.util.DatabaseUtils;
import com.android.providers.media.util.FileUtils;
import com.android.providers.media.util.ForegroundThread;
import com.android.providers.media.util.IsoInterface;
import com.android.providers.media.util.Logging;
import com.android.providers.media.util.LongArray;
import com.android.providers.media.util.Metrics;
import com.android.providers.media.util.MimeUtils;
import com.android.providers.media.util.PermissionUtils;
import com.android.providers.media.util.Preconditions;
import com.android.providers.media.util.SQLiteQueryBuilder;
import com.android.providers.media.util.SpecialFormatDetector;
import com.android.providers.media.util.StringUtils;
import com.android.providers.media.util.UserCache;
import com.android.providers.media.util.XAttrUtils;
import com.android.providers.media.util.XmpInterface;

import com.google.common.hash.Hashing;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * Media content provider. See {@link android.provider.MediaStore} for details.
 * Separate databases are kept for each external storage card we see (using the
 * card's ID as an index).  The content visible at content://media/external/...
 * changes with the card.
 */
public class MediaProvider extends ContentProvider {
    /**
     * Enables checks to stop apps from inserting and updating to private files via media provider.
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R)
    static final long ENABLE_CHECKS_FOR_PRIVATE_FILES = 172100307L;

    /**
     * Regex of a selection string that matches a specific ID.
     */
    static final Pattern PATTERN_SELECTION_ID = Pattern.compile(
            "(?:image_id|video_id)\\s*=\\s*(\\d+)");

    /** File access by uid requires the transcoding transform */
    private static final int FLAG_TRANSFORM_TRANSCODING = 1 << 0;

    /** File access by uid is a synthetic path corresponding to a redacted URI */
    private static final int FLAG_TRANSFORM_REDACTION = 1 << 1;

    /** File access by uid is a synthetic path corresponding to a picker URI */
    private static final int FLAG_TRANSFORM_PICKER = 1 << 2;

    /**
     * These directory names aren't declared in Environment as final variables, and so we need to
     * have the same values in separate final variables in order to have them considered constant
     * expressions.
     * These directory names are intentionally in lower case to ease the case insensitive path
     * comparison.
     */
    private static final String DIRECTORY_MUSIC_LOWER_CASE = "music";
    private static final String DIRECTORY_PODCASTS_LOWER_CASE = "podcasts";
    private static final String DIRECTORY_RINGTONES_LOWER_CASE = "ringtones";
    private static final String DIRECTORY_ALARMS_LOWER_CASE = "alarms";
    private static final String DIRECTORY_NOTIFICATIONS_LOWER_CASE = "notifications";
    private static final String DIRECTORY_PICTURES_LOWER_CASE = "pictures";
    private static final String DIRECTORY_MOVIES_LOWER_CASE = "movies";
    private static final String DIRECTORY_DOWNLOADS_LOWER_CASE = "download";
    private static final String DIRECTORY_DCIM_LOWER_CASE = "dcim";
    private static final String DIRECTORY_DOCUMENTS_LOWER_CASE = "documents";
    private static final String DIRECTORY_AUDIOBOOKS_LOWER_CASE = "audiobooks";
    private static final String DIRECTORY_RECORDINGS_LOWER_CASE = "recordings";
    private static final String DIRECTORY_ANDROID_LOWER_CASE = "android";

    private static final String DIRECTORY_MEDIA = "media";
    private static final String DIRECTORY_THUMBNAILS = ".thumbnails";

    /**
     * Hard-coded filename where the current value of
     * {@link DatabaseHelper#getOrCreateUuid} is persisted on a physical SD card
     * to help identify stale thumbnail collections.
     */
    private static final String FILE_DATABASE_UUID = ".database_uuid";

    /**
     * Specify what default directories the caller gets full access to. By default, the caller
     * shouldn't get full access to any default dirs.
     * But for example, we do an exception for System Gallery apps and allow them full access to:
     * DCIM, Pictures, Movies.
     */
    private static final String INCLUDED_DEFAULT_DIRECTORIES =
            "android:included-default-directories";

    /**
     * Value indicating that operations should include database rows matching the criteria defined
     * by this key only when calling package has write permission to the database row or column is
     * {@column MediaColumns#IS_PENDING} and is set by FUSE.
     * <p>
     * Note that items <em>not</em> matching the criteria will also be included, and as part of this
     * match no additional write permission checks are carried out for those items.
     */
    private static final int MATCH_VISIBLE_FOR_FILEPATH = 32;

    private static final int NON_HIDDEN_CACHE_SIZE = 50;

    /**
     * This is required as idle maintenance maybe stopped anytime; we do not want to query
     * and accumulate values to update for a long time, instead we want to batch query and update
     * by a limited number.
     */
    private static final int IDLE_MAINTENANCE_ROWS_LIMIT = 1000;

    /**
     * Where clause to match pending files from FUSE. Pending files from FUSE will not have
     * PATTERN_PENDING_FILEPATH_FOR_SQL pattern.
     */
    private static final String MATCH_PENDING_FROM_FUSE = String.format("lower(%s) NOT REGEXP '%s'",
            MediaColumns.DATA, PATTERN_PENDING_FILEPATH_FOR_SQL);

    /**
     * This flag is replaced with {@link MediaStore#QUERY_ARG_DEFER_SCAN} from S onwards and only
     * kept around for app compatibility in R.
     */
    private static final String QUERY_ARG_DO_ASYNC_SCAN = "android:query-arg-do-async-scan";
    /**
     * Enable option to defer the scan triggered as part of MediaProvider#update()
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.R)
    static final long ENABLE_DEFERRED_SCAN = 180326732L;

    /**
     * Enable option to include database rows of files from recently unmounted
     * volume in MediaProvider#query
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
    static final long ENABLE_INCLUDE_ALL_VOLUMES = 182734110L;

    /**
     * Set of {@link Cursor} columns that refer to raw filesystem paths.
     */
    private static final ArrayMap<String, Object> sDataColumns = new ArrayMap<>();

    static {
        sDataColumns.put(MediaStore.MediaColumns.DATA, null);
        sDataColumns.put(MediaStore.Images.Thumbnails.DATA, null);
        sDataColumns.put(MediaStore.Video.Thumbnails.DATA, null);
        sDataColumns.put(MediaStore.Audio.PlaylistsColumns.DATA, null);
        sDataColumns.put(MediaStore.Audio.AlbumColumns.ALBUM_ART, null);
    }

    private static final int sUserId = UserHandle.myUserId();

    /**
     * Please use {@link getDownloadsProviderAuthority()} instead of using this directly.
     */
    private static final String DOWNLOADS_PROVIDER_AUTHORITY = "downloads";

    @GuardedBy("mPendingOpenInfo")
    private final Map<Integer, PendingOpenInfo> mPendingOpenInfo = new ArrayMap<>();

    @GuardedBy("mNonHiddenPaths")
    private final LRUCache<String, Integer> mNonHiddenPaths = new LRUCache<>(NON_HIDDEN_CACHE_SIZE);

    public void updateVolumes() {
        mVolumeCache.update();
        // Update filters to reflect mounted volumes so users don't get
        // confused by metadata from ejected volumes
        ForegroundThread.getExecutor().execute(() -> {
            mExternalDatabase.setFilterVolumeNames(mVolumeCache.getExternalVolumeNames());
        });
    }

    public @NonNull MediaVolume getVolume(@NonNull String volumeName) throws FileNotFoundException {
        return mVolumeCache.findVolume(volumeName, mCallingIdentity.get().getUser());
    }

    public @NonNull File getVolumePath(@NonNull String volumeName) throws FileNotFoundException {
        // Ugly hack to keep unit tests passing, where we don't always have a
        // Context to discover volumes with
        if (getContext() == null) {
            return Environment.getExternalStorageDirectory();
        }

        return mVolumeCache.getVolumePath(volumeName, mCallingIdentity.get().getUser());
    }

    public @NonNull String getVolumeId(@NonNull File file) throws FileNotFoundException {
        return mVolumeCache.getVolumeId(file);
    }

    private @NonNull Collection<File> getAllowedVolumePaths(String volumeName)
            throws FileNotFoundException {
        // This method is used to verify whether a path belongs to a certain volume name;
        // we can't always use the calling user's identity here to determine exactly which
        // volume is meant, because the MediaScanner may scan paths belonging to another user,
        // eg a clone user.
        // So, for volumes like external_primary, just return allowed paths for all users.
        List<UserHandle> users = mUserCache.getUsersCached();
        ArrayList<File> allowedPaths = new ArrayList<>();
        for (UserHandle user : users) {
            Collection<File> volumeScanPaths = mVolumeCache.getVolumeScanPaths(volumeName, user);
            allowedPaths.addAll(volumeScanPaths);
        }

        return allowedPaths;
    }

    /**
     * Frees any cache held by MediaProvider.
     *
     * @param bytes number of bytes which need to be freed
     */
    public void freeCache(long bytes) {
        mTranscodeHelper.freeCache(bytes);
    }

    public void onAnrDelayStarted(@NonNull String packageName, int uid, int tid, int reason) {
        mTranscodeHelper.onAnrDelayStarted(packageName, uid, tid, reason);
    }

    private volatile Locale mLastLocale = Locale.getDefault();

    private StorageManager mStorageManager;
    private AppOpsManager mAppOpsManager;
    private PackageManager mPackageManager;
    private DevicePolicyManager mDevicePolicyManager;
    private UserManager mUserManager;
    private PickerUriResolver mPickerUriResolver;

    private UserCache mUserCache;
    private VolumeCache mVolumeCache;

    private int mExternalStorageAuthorityAppId;
    private int mDownloadsAuthorityAppId;
    private Size mThumbSize;

    /**
     * Map from UID to cached {@link LocalCallingIdentity}. Values are only
     * maintained in this map while the UID is actively working with a
     * performance-critical component, such as camera.
     */
    @GuardedBy("mCachedCallingIdentity")
    private final SparseArray<LocalCallingIdentity> mCachedCallingIdentity = new SparseArray<>();

    private final OnOpActiveChangedListener mActiveListener = (code, uid, packageName, active) -> {
        synchronized (mCachedCallingIdentity) {
            if (active) {
                // TODO moltmann: Set correct featureId
                mCachedCallingIdentity.put(uid,
                        LocalCallingIdentity.fromExternal(getContext(), mUserCache, uid,
                            packageName, null));
            } else {
                mCachedCallingIdentity.remove(uid);
            }
        }
    };

    /**
     * Map from UID to cached {@link LocalCallingIdentity}. Values are only
     * maintained in this map until there's any change in the appops needed or packages
     * used in the {@link LocalCallingIdentity}.
     */
    @GuardedBy("mCachedCallingIdentityForFuse")
    private final SparseArray<LocalCallingIdentity> mCachedCallingIdentityForFuse =
            new SparseArray<>();

    private OnOpChangedListener mModeListener =
            (op, packageName) -> invalidateLocalCallingIdentityCache(packageName, "op " + op);

    /**
     * Retrieves a cached calling identity or creates a new one. Also, always sets the app-op
     * description for the calling identity.
     */
    private LocalCallingIdentity getCachedCallingIdentityForFuse(int uid) {
        synchronized (mCachedCallingIdentityForFuse) {
            PermissionUtils.setOpDescription("via FUSE");
            LocalCallingIdentity identity = mCachedCallingIdentityForFuse.get(uid);
            if (identity == null) {
               identity = LocalCallingIdentity.fromExternal(getContext(), mUserCache, uid);
               if (uidToUserId(uid) == sUserId) {
                   mCachedCallingIdentityForFuse.put(uid, identity);
               } else {
                   // In some app cloning designs, MediaProvider user 0 may
                   // serve requests for apps running as a "clone" user; in
                   // those cases, don't keep a cache for the clone user, since
                   // we don't get any invalidation events for these users.
               }
            }
            return identity;
        }
    }

    /**
     * Calling identity state about on the current thread. Populated on demand,
     * and invalidated by {@link #onCallingPackageChanged()} when each remote
     * call is finished.
     */
    private final ThreadLocal<LocalCallingIdentity> mCallingIdentity = ThreadLocal
            .withInitial(() -> {
                PermissionUtils.setOpDescription("via MediaProvider");
                synchronized (mCachedCallingIdentity) {
                    final LocalCallingIdentity cached = mCachedCallingIdentity
                            .get(Binder.getCallingUid());
                    return (cached != null) ? cached
                            : LocalCallingIdentity.fromBinder(getContext(), this, mUserCache);
                }
            });

    /**
     * We simply propagate the UID that is being tracked by
     * {@link LocalCallingIdentity}, which means we accurately blame both
     * incoming Binder calls and FUSE calls.
     */
    private final ProxyTransactListener mTransactListener = new ProxyTransactListener() {
        @Override
        public Object onTransactStarted(IBinder binder, int transactionCode) {
            if (LOGV) Trace.beginSection(Thread.currentThread().getStackTrace()[5].getMethodName());
            return Binder.setCallingWorkSourceUid(mCallingIdentity.get().uid);
        }

        @Override
        public void onTransactEnded(Object session) {
            final long token = (long) session;
            Binder.restoreCallingWorkSource(token);
            if (LOGV) Trace.endSection();
        }
    };

    // In memory cache of path<->id mappings, to speed up inserts during media scan
    @GuardedBy("mDirectoryCache")
    private final ArrayMap<String, Long> mDirectoryCache = new ArrayMap<>();

    private static final String[] sDataOnlyColumn = new String[] {
        FileColumns.DATA
    };

    private static final String ID_NOT_PARENT_CLAUSE =
            "_id NOT IN (SELECT parent FROM files WHERE parent IS NOT NULL)";

    private static final String CANONICAL = "canonical";

    private static final String ALL_VOLUMES = "all_volumes";

    private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case Intent.ACTION_PACKAGE_REMOVED:
                case Intent.ACTION_PACKAGE_ADDED:
                    Uri uri = intent.getData();
                    String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
                    if (pkg != null) {
                        invalidateLocalCallingIdentityCache(pkg, "package " + intent.getAction());
                        if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                            mUserCache.invalidateWorkProfileOwnerApps(pkg);
                            mPickerSyncController.notifyPackageRemoval(pkg);
                        }
                    } else {
                        Log.w(TAG, "Failed to retrieve package from intent: " + intent.getAction());
                    }
                    break;
            }
        }
    };

    private BroadcastReceiver mUserIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case Intent.ACTION_USER_REMOVED:
                    /**
                     * Removing media files for user being deleted. This would impact if the deleted
                     * user have been using same MediaProvider as the current user i.e. when
                     * isMediaSharedWithParent is true.On removal of such user profile,
                     * the owner's MediaProvider would need to clean any media files stored
                     * by the removed user profile.
                     */
                    UserHandle userToBeRemoved  = intent.getParcelableExtra(Intent.EXTRA_USER);
                    if(userToBeRemoved.getIdentifier() != sUserId){
                        mExternalDatabase.runWithTransaction((db) -> {
                            db.execSQL("delete from files where _user_id=?",
                                    new String[]{String.valueOf(userToBeRemoved.getIdentifier())});
                            return null ;
                        });
                    }
                    break;
            }
        }
    };


    private void invalidateLocalCallingIdentityCache(String packageName, String reason) {
        synchronized (mCachedCallingIdentityForFuse) {
            try {
                Log.i(TAG, "Invalidating LocalCallingIdentity cache for package " + packageName
                        + ". Reason: " + reason);
                mCachedCallingIdentityForFuse.remove(
                        getContext().getPackageManager().getPackageUid(packageName, 0));
            } catch (NameNotFoundException ignored) {
            }
        }
    }

    private final void updateQuotaTypeForUri(@NonNull Uri uri, int mediaType) {
        Trace.beginSection("updateQuotaTypeForUri");
        File file;
        try {
            file = queryForDataFile(uri, null);
            if (!file.exists()) {
                // This can happen if an item is inserted in MediaStore before it is created
                return;
            }

            if (mediaType == FileColumns.MEDIA_TYPE_NONE) {
                // This might be because the file is hidden; but we still want to
                // attribute its quota to the correct type, so get the type from
                // the extension instead.
                mediaType = MimeUtils.resolveMediaType(MimeUtils.resolveMimeType(file));
            }

            updateQuotaTypeForFileInternal(file, mediaType);
        } catch (FileNotFoundException | IllegalArgumentException e) {
            // Ignore
            Log.w(TAG, "Failed to update quota for uri: " + uri, e);
            return;
        } finally {
            Trace.endSection();
        }
    }

    private final void updateQuotaTypeForFileInternal(File file, int mediaType) {
        try {
            switch (mediaType) {
                case FileColumns.MEDIA_TYPE_AUDIO:
                    mStorageManager.updateExternalStorageFileQuotaType(file,
                            StorageManager.QUOTA_TYPE_MEDIA_AUDIO);
                    break;
                case FileColumns.MEDIA_TYPE_VIDEO:
                    mStorageManager.updateExternalStorageFileQuotaType(file,
                            StorageManager.QUOTA_TYPE_MEDIA_VIDEO);
                    break;
                case FileColumns.MEDIA_TYPE_IMAGE:
                    mStorageManager.updateExternalStorageFileQuotaType(file,
                            StorageManager.QUOTA_TYPE_MEDIA_IMAGE);
                    break;
                default:
                    mStorageManager.updateExternalStorageFileQuotaType(file,
                            StorageManager.QUOTA_TYPE_MEDIA_NONE);
                    break;
            }
        } catch (IOException e) {
            Log.w(TAG, "Failed to update quota type for " + file.getPath(), e);
        }
    }

    /**
     * Since these operations are in the critical path of apps working with
     * media, we only collect the {@link Uri} that need to be notified, and all
     * other side-effect operations are delegated to {@link BackgroundThread} so
     * that we return as quickly as possible.
     */
    private final OnFilesChangeListener mFilesListener = new OnFilesChangeListener() {
        @Override
        public void onInsert(@NonNull DatabaseHelper helper, @NonNull FileRow insertedRow) {
            handleInsertedRowForFuse(insertedRow.getId());
            acceptWithExpansion(helper::notifyInsert, insertedRow.getVolumeName(),
                    insertedRow.getId(), insertedRow.getMediaType(), insertedRow.isDownload());
            updateNextRowIdXattr(helper, insertedRow.getId());
            helper.postBackground(() -> {
                if (helper.isExternal()) {
                    // Update the quota type on the filesystem
                    Uri fileUri = MediaStore.Files.getContentUri(insertedRow.getVolumeName(),
                            insertedRow.getId());
                    updateQuotaTypeForUri(fileUri, insertedRow.getMediaType());
                }

                // Tell our SAF provider so it knows when views are no longer empty
                MediaDocumentsProvider.onMediaStoreInsert(getContext(), insertedRow.getVolumeName(),
                        insertedRow.getMediaType(), insertedRow.getId());

                if (mExternalDbFacade.onFileInserted(insertedRow.getMediaType(),
                        insertedRow.isPending())) {
                    mPickerSyncController.notifyMediaEvent();
                }
            });
        }

        @Override
        public void onUpdate(@NonNull DatabaseHelper helper, @NonNull FileRow oldRow,
                @NonNull FileRow newRow) {
            final boolean isDownload = oldRow.isDownload() || newRow.isDownload();
            final Uri fileUri = MediaStore.Files.getContentUri(oldRow.getVolumeName(),
                    oldRow.getId());
            handleUpdatedRowForFuse(oldRow.getPath(), oldRow.getOwnerPackageName(), oldRow.getId(),
                    newRow.getId());
            handleOwnerPackageNameChange(oldRow.getPath(), oldRow.getOwnerPackageName(),
                    newRow.getOwnerPackageName());
            acceptWithExpansion(helper::notifyUpdate, oldRow.getVolumeName(), oldRow.getId(),
                    oldRow.getMediaType(), isDownload);
            updateNextRowIdXattr(helper, newRow.getId());
            helper.postBackground(() -> {
                if (helper.isExternal()) {
                    // Update the quota type on the filesystem
                    updateQuotaTypeForUri(fileUri, newRow.getMediaType());
                }

                if (mExternalDbFacade.onFileUpdated(oldRow.getId(),
                        oldRow.getMediaType(), newRow.getMediaType(),
                        oldRow.isTrashed(), newRow.isTrashed(),
                        oldRow.isPending(), newRow.isPending(),
                        oldRow.isFavorite(), newRow.isFavorite(),
                        oldRow.getSpecialFormat(), newRow.getSpecialFormat())) {
                    mPickerSyncController.notifyMediaEvent();
                }
            });

            if (newRow.getMediaType() != oldRow.getMediaType()) {
                acceptWithExpansion(helper::notifyUpdate, oldRow.getVolumeName(), oldRow.getId(),
                        newRow.getMediaType(), isDownload);

                helper.postBackground(() -> {
                    // Invalidate any thumbnails when the media type changes
                    invalidateThumbnails(fileUri);
                });
            }
        }

        @Override
        public void onDelete(@NonNull DatabaseHelper helper, @NonNull FileRow deletedRow) {
            handleDeletedRowForFuse(deletedRow.getPath(), deletedRow.getOwnerPackageName(),
                    deletedRow.getId());
            acceptWithExpansion(helper::notifyDelete, deletedRow.getVolumeName(),
                    deletedRow.getId(), deletedRow.getMediaType(), deletedRow.isDownload());
            // Remove cached transcoded file if any
            mTranscodeHelper.deleteCachedTranscodeFile(deletedRow.getId());

            helper.postBackground(() -> {
                // Item no longer exists, so revoke all access to it
                Trace.beginSection("revokeUriPermission");
                try {
                    acceptWithExpansion((uri) -> {
                        getContext().revokeUriPermission(uri, ~0);
                    },
                            deletedRow.getVolumeName(), deletedRow.getId(),
                            deletedRow.getMediaType(), deletedRow.isDownload());
                } finally {
                    Trace.endSection();
                }

                switch (deletedRow.getMediaType()) {
                    case FileColumns.MEDIA_TYPE_PLAYLIST:
                    case FileColumns.MEDIA_TYPE_AUDIO:
                        if (helper.isExternal()) {
                            removePlaylistMembers(deletedRow.getMediaType(), deletedRow.getId());
                        }
                }

                // Invalidate any thumbnails now that media is gone
                invalidateThumbnails(MediaStore.Files.getContentUri(deletedRow.getVolumeName(),
                        deletedRow.getId()));

                // Tell our SAF provider so it can revoke too
                MediaDocumentsProvider.onMediaStoreDelete(getContext(), deletedRow.getVolumeName(),
                        deletedRow.getMediaType(), deletedRow.getId());

                if (mExternalDbFacade.onFileDeleted(deletedRow.getId(),
                        deletedRow.getMediaType())) {
                    mPickerSyncController.notifyMediaEvent();
                }
            });
        }
    };

    protected void updateNextRowIdXattr(DatabaseHelper helper, long id) {
        if (!helper.isNextRowIdBackupEnabled()) {
            Log.v(TAG, "Skipping next row id backup.");
            return;
        }

        Optional<Long> nextRowIdBackupOptional = helper.getNextRowId();
        if (!nextRowIdBackupOptional.isPresent()) {
            throw new RuntimeException(
                    String.format(Locale.ROOT, "Cannot find next row id xattr for %s.",
                            helper.getDatabaseName()));
        }

        if (id >= nextRowIdBackupOptional.get()) {
            helper.backupNextRowId(id);
        } else {
            Log.v(TAG, String.format(Locale.ROOT, "Inserted id:%d less than next row id backup:%d.",
                    id, nextRowIdBackupOptional.get()));
        }
    }

    private final UnaryOperator<String> mIdGenerator = path -> {
        final long rowId = mCallingIdentity.get().getDeletedRowId(path);
        if (rowId != -1 && isFuseThread()) {
            return String.valueOf(rowId);
        }
        return null;
    };

    /** {@hide} */
    public static final OnLegacyMigrationListener MIGRATION_LISTENER =
            new OnLegacyMigrationListener() {
        @Override
        public void onStarted(ContentProviderClient client, String volumeName) {
            MediaStore.startLegacyMigration(ContentResolver.wrap(client), volumeName);
        }

        @Override
        public void onProgress(ContentProviderClient client, String volumeName,
                long progress, long total) {
            // TODO: notify blocked threads of progress once we can change APIs
        }

        @Override
        public void onFinished(ContentProviderClient client, String volumeName) {
            MediaStore.finishLegacyMigration(ContentResolver.wrap(client), volumeName);
        }
    };

    /**
     * Apply {@link Consumer#accept} to the given item.
     * <p>
     * Since media items can be exposed through multiple collections or views,
     * this method expands the single item being accepted to also accept all
     * relevant views.
     */
    private void acceptWithExpansion(@NonNull Consumer<Uri> consumer, @NonNull String volumeName,
            long id, int mediaType, boolean isDownload) {
        switch (mediaType) {
            case FileColumns.MEDIA_TYPE_AUDIO:
                consumer.accept(MediaStore.Audio.Media.getContentUri(volumeName, id));

                // Any changing audio items mean we probably need to invalidate all
                // indexed views built from that media
                consumer.accept(Audio.Genres.getContentUri(volumeName));
                consumer.accept(Audio.Playlists.getContentUri(volumeName));
                consumer.accept(Audio.Artists.getContentUri(volumeName));
                consumer.accept(Audio.Albums.getContentUri(volumeName));
                break;

            case FileColumns.MEDIA_TYPE_VIDEO:
                consumer.accept(MediaStore.Video.Media.getContentUri(volumeName, id));
                break;

            case FileColumns.MEDIA_TYPE_IMAGE:
                consumer.accept(MediaStore.Images.Media.getContentUri(volumeName, id));
                break;

            case FileColumns.MEDIA_TYPE_PLAYLIST:
                consumer.accept(ContentUris.withAppendedId(
                        MediaStore.Audio.Playlists.getContentUri(volumeName), id));
                break;
        }

        // Also notify through any generic views
        consumer.accept(MediaStore.Files.getContentUri(volumeName, id));
        if (isDownload) {
            consumer.accept(MediaStore.Downloads.getContentUri(volumeName, id));
        }

        // Rinse and repeat through any synthetic views
        switch (volumeName) {
            case MediaStore.VOLUME_INTERNAL:
            case MediaStore.VOLUME_EXTERNAL:
                // Already a top-level view, no need to expand
                break;
            default:
                acceptWithExpansion(consumer, MediaStore.VOLUME_EXTERNAL,
                        id, mediaType, isDownload);
                break;
        }
    }

    /**
     * Ensure that default folders are created on mounted storage devices.
     * We only do this once per volume so we don't annoy the user if deleted
     * manually.
     */
    private void ensureDefaultFolders(@NonNull MediaVolume volume, @NonNull SQLiteDatabase db) {
        if (volume.isExternallyManaged()) {
            // Default folders should not be automatically created inside volumes managed from
            // outside Android.
            return;
        }
        final String volumeName = volume.getName();
        String key;
        if (volumeName.equals(MediaStore.VOLUME_EXTERNAL_PRIMARY)) {
            // For the primary volume, we use the ID, because we may be handling
            // the primary volume for multiple users
            key = "created_default_folders_" + volume.getId();
        } else {
            // For others, like public volumes, just use the name, because the id
            // might not change when re-formatted
            key = "created_default_folders_" + volumeName;
        }

        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
        if (prefs.getInt(key, 0) == 0) {
            for (String folderName : DEFAULT_FOLDER_NAMES) {
                final File folder = new File(volume.getPath(), folderName);
                if (!folder.exists()) {
                    folder.mkdirs();
                    insertDirectory(db, folder.getAbsolutePath());
                }
            }

            SharedPreferences.Editor editor = prefs.edit();
            editor.putInt(key, 1);
            editor.commit();
        }
    }

    /**
     * Ensure that any thumbnail collections on the given storage volume can be
     * used with the given {@link DatabaseHelper}. If the
     * {@link DatabaseHelper#getOrCreateUuid} doesn't match the UUID found on
     * disk, then all thumbnails will be considered stable and will be deleted.
     */
    private void ensureThumbnailsValid(@NonNull MediaVolume volume, @NonNull SQLiteDatabase db) {
        if (volume.isExternallyManaged()) {
            // Default folders and thumbnail directories should not be automatically created inside
            // volumes managed from outside Android, and there is no need to ensure the validity of
            // their thumbnails here.
            return;
        }
        final String uuidFromDatabase = DatabaseHelper.getOrCreateUuid(db);
        try {
            for (File dir : getThumbnailDirectories(volume)) {
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                final File file = new File(dir, FILE_DATABASE_UUID);
                final Optional<String> uuidFromDisk = FileUtils.readString(file);

                final boolean updateUuid;
                if (!uuidFromDisk.isPresent()) {
                    // For newly inserted volumes or upgrading of existing volumes,
                    // assume that our current UUID is valid
                    updateUuid = true;
                } else if (!Objects.equals(uuidFromDatabase, uuidFromDisk.get())) {
                    // The UUID of database disagrees with the one on disk,
                    // which means we can't trust any thumbnails
                    Log.d(TAG, "Invalidating all thumbnails under " + dir);
                    FileUtils.walkFileTreeContents(dir.toPath(), this::deleteAndInvalidate);
                    updateUuid = true;
                } else {
                    updateUuid = false;
                }

                if (updateUuid) {
                    FileUtils.writeString(file, Optional.of(uuidFromDatabase));
                }
            }
        } catch (IOException e) {
            Log.w(TAG, "Failed to ensure thumbnails valid for " + volume.getName(), e);
        }
    }

    @Override
    public void attachInfo(Context context, ProviderInfo info) {
        Log.v(TAG, "Attached " + info.authority + " from " + info.applicationInfo.packageName);

        mUriMatcher = new LocalUriMatcher(info.authority);

        super.attachInfo(context, info);
    }

    @Override
    public boolean onCreate() {
        final Context context = getContext();

        mUserCache = new UserCache(context);

        // Shift call statistics back to the original caller
        Binder.setProxyTransactListener(mTransactListener);

        mStorageManager = context.getSystemService(StorageManager.class);
        mAppOpsManager = context.getSystemService(AppOpsManager.class);
        mPackageManager = context.getPackageManager();
        mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
        mUserManager = context.getSystemService(UserManager.class);
        mVolumeCache = new VolumeCache(context, mUserCache);

        // Reasonable thumbnail size is half of the smallest screen edge width
        final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        final int thumbSize = Math.min(metrics.widthPixels, metrics.heightPixels) / 2;
        mThumbSize = new Size(thumbSize, thumbSize);

        mMediaScanner = new ModernMediaScanner(context);

        mInternalDatabase = new DatabaseHelper(context, INTERNAL_DATABASE_NAME, false, false,
                Column.class, ExportedSince.class, Metrics::logSchemaChange, mFilesListener,
                MIGRATION_LISTENER, mIdGenerator, true);
        mExternalDatabase = new DatabaseHelper(context, EXTERNAL_DATABASE_NAME, false, false,
                Column.class, ExportedSince.class, Metrics::logSchemaChange, mFilesListener,
                MIGRATION_LISTENER, mIdGenerator, true);
        mExternalDbFacade = new ExternalDbFacade(getContext(), mExternalDatabase, mVolumeCache);
        mPickerDbFacade = new PickerDbFacade(context);

        final String localPickerProvider = PickerSyncController.LOCAL_PICKER_PROVIDER_AUTHORITY;
        final String allowedCloudProviders =
                getStringDeviceConfig(PickerSyncController.ALLOWED_CLOUD_PROVIDERS_KEY,
                        /* default */ "");
        final int pickerSyncDelayMs = getIntDeviceConfig(PickerSyncController.SYNC_DELAY_MS,
                /* default */ 5000);

        mPickerSyncController = new PickerSyncController(context, mPickerDbFacade,
                localPickerProvider, allowedCloudProviders, pickerSyncDelayMs);
        mPickerDataLayer = new PickerDataLayer(context, mPickerDbFacade, mPickerSyncController);
        mPickerUriResolver = new PickerUriResolver(context, mPickerDbFacade);

        if (SdkLevel.isAtLeastS()) {
            mTranscodeHelper = new TranscodeHelperImpl(context, this);
        } else {
            mTranscodeHelper = new TranscodeHelperNoOp();
        }

        // Create dir for redacted and picker URI paths.
        buildPrimaryVolumeFile(uidToUserId(MY_UID), getRedactedRelativePath()).mkdirs();

        final IntentFilter packageFilter = new IntentFilter();
        packageFilter.setPriority(10);
        packageFilter.addDataScheme("package");
        packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        context.registerReceiver(mPackageReceiver, packageFilter);

        // Creating intent broadcast receiver for user actions like Intent.ACTION_USER_REMOVED,
        // where we would need to remove files stored by removed user.
        final IntentFilter userIntentFilter = new IntentFilter();
        userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
        context.registerReceiver(mUserIntentReceiver, userIntentFilter);

        // Watch for invalidation of cached volumes
        mStorageManager.registerStorageVolumeCallback(context.getMainExecutor(),
                new StorageVolumeCallback() {
                    @Override
                    public void onStateChanged(@NonNull StorageVolume volume) {
                        updateVolumes();
                    }
                });

        if (SdkLevel.isAtLeastT()) {
            try {
                mStorageManager.setCloudMediaProvider(mPickerSyncController.getCloudProvider());
            } catch (SecurityException e) {
                // This can happen in unit tests
                Log.w(TAG, "Failed to update the system_server with the latest cloud provider", e);
            }
        }

        updateVolumes();
        attachVolume(MediaVolume.fromInternal(), /* validate */ false);
        for (MediaVolume volume : mVolumeCache.getExternalVolumes()) {
            attachVolume(volume, /* validate */ false);
        }

        // Watch for performance-sensitive activity
        mAppOpsManager.startWatchingActive(new String[] {
                AppOpsManager.OPSTR_CAMERA
        }, context.getMainExecutor(), mActiveListener);

        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_READ_MEDIA_AUDIO,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_READ_MEDIA_IMAGES,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_READ_MEDIA_VIDEO,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_WRITE_EXTERNAL_STORAGE,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(permissionToOp(ACCESS_MEDIA_LOCATION),
                null /* all packages */, mModeListener);
        // Legacy apps
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_LEGACY_STORAGE,
                null /* all packages */, mModeListener);
        // File managers
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_MANAGE_EXTERNAL_STORAGE,
                null /* all packages */, mModeListener);
        // Default gallery changes
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_WRITE_MEDIA_IMAGES,
                null /* all packages */, mModeListener);
        mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_WRITE_MEDIA_VIDEO,
                null /* all packages */, mModeListener);
        try {
            // Here we are forced to depend on the non-public API of AppOpsManager. If
            // OPSTR_NO_ISOLATED_STORAGE app op is not defined in AppOpsManager, then this call will
            // throw an IllegalArgumentException during MediaProvider startup. In combination with
            // MediaProvider's CTS tests it should give us guarantees that OPSTR_NO_ISOLATED_STORAGE
            // is defined.
            mAppOpsManager.startWatchingMode(AppOpsManager.OPSTR_NO_ISOLATED_STORAGE,
                    null /* all packages */, mModeListener);
        } catch (IllegalArgumentException e) {
            Log.w(TAG, "Failed to start watching " + AppOpsManager.OPSTR_NO_ISOLATED_STORAGE, e);
        }

        ProviderInfo provider = mPackageManager.resolveContentProvider(
                getDownloadsProviderAuthority(), PackageManager.MATCH_DIRECT_BOOT_AWARE
                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
        if (provider != null) {
            mDownloadsAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
        }

        provider = mPackageManager.resolveContentProvider(getExternalStorageProviderAuthority(),
                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
        if (provider != null) {
            mExternalStorageAuthorityAppId = UserHandle.getAppId(provider.applicationInfo.uid);
        }

        PulledMetrics.initialize(context);
        return true;
    }

    Optional<DatabaseHelper> getDatabaseHelper(String dbName) {
        if (dbName.equalsIgnoreCase(INTERNAL_DATABASE_NAME)) {
            return Optional.of(mInternalDatabase);
        } else if (dbName.equalsIgnoreCase(EXTERNAL_DATABASE_NAME)) {
            return Optional.of(mExternalDatabase);
        }

        return Optional.empty();
    }

    @Override
    public void onCallingPackageChanged() {
        // Identity of the current thread has changed, so invalidate caches
        mCallingIdentity.remove();
    }

    public LocalCallingIdentity clearLocalCallingIdentity() {
        // We retain the user part of the calling identity, since we are executing
        // the call on behalf of that user, and we need to maintain the user context
        // to correctly resolve things like volumes
        UserHandle user = mCallingIdentity.get().getUser();
        return clearLocalCallingIdentity(LocalCallingIdentity.fromSelfAsUser(getContext(), user));
    }

    public LocalCallingIdentity clearLocalCallingIdentity(LocalCallingIdentity replacement) {
        final LocalCallingIdentity token = mCallingIdentity.get();
        mCallingIdentity.set(replacement);
        return token;
    }

    public void restoreLocalCallingIdentity(LocalCallingIdentity token) {
        mCallingIdentity.set(token);
    }

    private boolean isPackageKnown(@NonNull String packageName, int userId) {
        final Context context = mUserCache.getContextForUser(UserHandle.of(userId));
        final PackageManager pm = context.getPackageManager();

        // First, is the app actually installed?
        try {
            pm.getPackageInfo(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES);
            return true;
        } catch (NameNotFoundException ignored) {
        }

        // Second, is the app pending, probably from a backup/restore operation?
        for (SessionInfo si : pm.getPackageInstaller().getAllSessions()) {
            if (Objects.equals(packageName, si.getAppPackageName())) {
                return true;
            }
        }

        // I've never met this package in my life
        return false;
    }

    public void onIdleMaintenance(@NonNull CancellationSignal signal) {
        final long startTime = SystemClock.elapsedRealtime();
        // Trim any stale log files before we emit new events below
        Logging.trimPersistent();

        // Scan all volumes to resolve any staleness
        for (MediaVolume volume : mVolumeCache.getExternalVolumes()) {
            // Possibly bail before digging into each volume
            signal.throwIfCanceled();

            try {
                MediaService.onScanVolume(getContext(), volume, REASON_IDLE);
            } catch (IOException e) {
                Log.w(TAG, e);
            }

            // Ensure that our thumbnails are valid
            mExternalDatabase.runWithTransaction((db) -> {
                ensureThumbnailsValid(volume, db);
                return null;
            });
        }

        // Delete any stale thumbnails
        final int staleThumbnails = mExternalDatabase.runWithTransaction((db) -> {
            return pruneThumbnails(db, signal);
        });
        Log.d(TAG, "Pruned " + staleThumbnails + " unknown thumbnails");

        // Finished orphaning any content whose package no longer exists
        pruneStalePackages(signal);

        // Delete the expired items or extend them on mounted volumes
        final int[] result = deleteOrExtendExpiredItems(signal);
        final int deletedExpiredMedia = result[0];
        Log.d(TAG, "Deleted " + deletedExpiredMedia + " expired items");
        Log.d(TAG, "Extended " + result[1] + " expired items");

        // Forget any stale volumes
        deleteStaleVolumes(signal);

        final long itemCount = mExternalDatabase.runWithTransaction((db) -> {
            return DatabaseHelper.getItemCount(db);
        });

        // Cleaning media files for users that have been removed
        cleanMediaFilesForRemovedUser(signal);

        // Populate _SPECIAL_FORMAT column for files which have column value as NULL
        detectSpecialFormat(signal);

        final long durationMillis = (SystemClock.elapsedRealtime() - startTime);
        Metrics.logIdleMaintenance(MediaStore.VOLUME_EXTERNAL, itemCount,
                durationMillis, staleThumbnails, deletedExpiredMedia);
    }

    /**
     * This function find and clean the files related to user who have been removed
     */
    private void cleanMediaFilesForRemovedUser(CancellationSignal signal) {
        //Finding userIds that are available in database
        final List<String> userIds = mExternalDatabase.runWithTransaction((db) -> {
            final List<String> userIdsPresent = new ArrayList<>();
            try (Cursor c = db.query(true, "files", new String[] { "_user_id" },
                    null, null, null, null, null,
                    null, signal)) {
                while (c.moveToNext()) {
                    final String userId = c.getString(0);
                    userIdsPresent.add(userId);
                }
            }
            return userIdsPresent;
        });

        //removing calling userId
        userIds.remove(String.valueOf(sUserId));
        //removing all the valid/existing user, remaining userIds would be users who would have been
        //removed
        userIds.removeAll(mUserManager.getEnabledProfiles().stream()
                .map(userHandle -> String.valueOf(userHandle.getIdentifier())).collect(
                        Collectors.toList()));

        // Cleaning media files of users who have been removed
        mExternalDatabase.runWithTransaction((db) -> {
            userIds.stream().forEach(userId ->{
                Log.d(TAG, "Removing media files associated with user : " + userId);
                db.execSQL("delete from files where _user_id=?",
                        new String[]{String.valueOf(userId)});
            });
            return null ;
        });
    }

    private void pruneStalePackages(CancellationSignal signal) {
        final int stalePackages = mExternalDatabase.runWithTransaction((db) -> {
            final ArraySet<Pair<String, Integer>> unknownPackages = new ArraySet<>();
            try (Cursor c = db.query(true, "files",
                    new String[] { "owner_package_name", "_user_id" },
                    null, null, null, null, null, null, signal)) {
                while (c.moveToNext()) {
                    final String packageName = c.getString(0);
                    if (TextUtils.isEmpty(packageName)) continue;

                    final int userId = c.getInt(1);

                    if (!isPackageKnown(packageName, userId)) {
                        unknownPackages.add(Pair.create(packageName, userId));
                    }
                }
            }
            for (Pair<String, Integer> pair : unknownPackages) {
                onPackageOrphaned(db, pair.first, pair.second);
            }
            return unknownPackages.size();
        });
        Log.d(TAG, "Pruned " + stalePackages + " unknown packages");
    }

    private void deleteStaleVolumes(CancellationSignal signal) {
        mExternalDatabase.runWithTransaction((db) -> {
            final Set<String> recentVolumeNames = MediaStore
                    .getRecentExternalVolumeNames(getContext());
            final Set<String> knownVolumeNames = new ArraySet<>();
            try (Cursor c = db.query(true, "files", new String[] { MediaColumns.VOLUME_NAME },
                    null, null, null, null, null, null, signal)) {
                while (c.moveToNext()) {
                    knownVolumeNames.add(c.getString(0));
                }
            }
            final Set<String> staleVolumeNames = new ArraySet<>();
            staleVolumeNames.addAll(knownVolumeNames);
            staleVolumeNames.removeAll(recentVolumeNames);
            for (String staleVolumeName : staleVolumeNames) {
                final int num = db.delete("files", FileColumns.VOLUME_NAME + "=?",
                        new String[] { staleVolumeName });
                Log.d(TAG, "Forgot " + num + " stale items from " + staleVolumeName);
            }
            return null;
        });

        synchronized (mDirectoryCache) {
            mDirectoryCache.clear();
        }
    }

    @VisibleForTesting
    public void setUriResolver(PickerUriResolver resolver) {
        Log.w(TAG, "Changing the PickerUriResolver!!! Should only be called during test");
        mPickerUriResolver = resolver;
    }

    @VisibleForTesting
    void detectSpecialFormat(@NonNull CancellationSignal signal) {
        mExternalDatabase.runWithTransaction((db) -> {
            updateSpecialFormatColumn(db, signal);
            return null;
        });
    }

    private void updateSpecialFormatColumn(SQLiteDatabase db, @NonNull CancellationSignal signal) {
        // This is to ensure we only do a bounded iteration over the rows as updates can fail, and
        // we don't want to keep running the query/update indefinitely.
        final int totalRowsToUpdate = getPendingSpecialFormatRowsCount(db,signal);
        for (int i = 0 ; i < totalRowsToUpdate ; i += IDLE_MAINTENANCE_ROWS_LIMIT) {
            updateSpecialFormatForLimitedRows(db, signal);
        }
    }

    private int getPendingSpecialFormatRowsCount(SQLiteDatabase db,
            @NonNull CancellationSignal signal) {
        try (Cursor c = queryForPendingSpecialFormatColumns(db, /* limit */ null, signal)) {
            if (c == null) {
                return 0;
            }
            return c.getCount();
        }
    }

    private void updateSpecialFormatForLimitedRows(SQLiteDatabase db,
            @NonNull CancellationSignal signal) {
        final SQLiteQueryBuilder qbForUpdate = getQueryBuilder(TYPE_UPDATE, FILES,
                Files.getContentUri(VOLUME_EXTERNAL), Bundle.EMPTY, null);
        // Accumulate all the new SPECIAL_FORMAT updates with their ids
        ArrayMap<Long, Integer> newSpecialFormatValues = new ArrayMap<>();
        final String limit = String.valueOf(IDLE_MAINTENANCE_ROWS_LIMIT);
        try (Cursor c = queryForPendingSpecialFormatColumns(db, limit, signal)) {
            while (c.moveToNext() && !signal.isCanceled()) {
                final long id = c.getLong(0);
                final String path = c.getString(1);
                newSpecialFormatValues.put(id, getSpecialFormatValue(path));
            }
        }

        // Now, update all the new SPECIAL_FORMAT values.
        final ContentValues values = new ContentValues();
        int count = 0;
        for (long id: newSpecialFormatValues.keySet()) {
            if (signal.isCanceled()) {
                return;
            }

            values.clear();
            values.put(_SPECIAL_FORMAT, newSpecialFormatValues.get(id));
            final String selection = MediaColumns._ID + "=?";
            final String[] selectionArgs = new String[]{String.valueOf(id)};
            if (qbForUpdate.update(db, values, selection, selectionArgs) == 1) {
                count++;
            } else {
                Log.e(TAG, "Unable to update _SPECIAL_FORMAT for id = " + id);
            }
        }
        Log.d(TAG, "Updated _SPECIAL_FORMAT for " + count + " items");
    }

    private int getSpecialFormatValue(String path) {
        final File file = new File(path);
        if (!file.exists()) {
            // We always update special format to none if the file is not found or there is an
            // error, this is so that we do not repeat over the same column again and again.
            return _SPECIAL_FORMAT_NONE;
        }

        try {
            return SpecialFormatDetector.detect(file);
        } catch (Exception e) {
            // we tried our best, no need to run special detection again and again if it
            // throws exception once, it is likely to do so everytime.
            Log.d(TAG, "Failed to detect special format for file: " + file, e);
            return _SPECIAL_FORMAT_NONE;
        }
    }

    private Cursor queryForPendingSpecialFormatColumns(SQLiteDatabase db, String limit,
            @NonNull CancellationSignal signal) {
        // Run special detection for images only
        final String selection = _SPECIAL_FORMAT + " IS NULL AND "
                + MEDIA_TYPE + "=" + MEDIA_TYPE_IMAGE;
        final String[] projection = new String[] { MediaColumns._ID, MediaColumns.DATA };
        return db.query(/* distinct */ true, "files", projection, selection, null, null, null,
                null, limit, signal);
    }

    /**
     * Delete any expired content on mounted volumes. The expired content on unmounted
     * volumes will be deleted when we forget any stale volumes; we're cautious about
     * wildly changing clocks, so only delete items within the last week.
     * If the items are expired more than one week, extend the expired time of them
     * another one week to avoid data loss with incorrect time zone data. We will
     * delete it when it is expired next time.
     *
     * @param signal the cancellation signal
     * @return the integer array includes total deleted count and total extended count
     */
    @NonNull
    private int[] deleteOrExtendExpiredItems(@NonNull CancellationSignal signal) {
        final long expiredOneWeek =
                ((System.currentTimeMillis() - DateUtils.WEEK_IN_MILLIS) / 1000);
        final long now = (System.currentTimeMillis() / 1000);
        final Long expiredTime = now + (FileUtils.DEFAULT_DURATION_EXTENDED / 1000);
        final int result[] = mExternalDatabase.runWithTransaction((db) -> {
            String selection = FileColumns.DATE_EXPIRES + " < " + now;
            selection += " AND volume_name in " + bindList(MediaStore.getExternalVolumeNames(
                    getContext()).toArray());
            String[] projection = new String[]{"volume_name", "_id",
                    FileColumns.DATE_EXPIRES, FileColumns.DATA};
            try (Cursor c = db.query(true, "files", projection, selection, null, null, null, null,
                    null, signal)) {
                int totalDeleteCount = 0;
                int totalExtendedCount = 0;
                int index = 0;
                while (c.moveToNext()) {
                    final String volumeName = c.getString(0);
                    final long id = c.getLong(1);
                    final long dateExpires = c.getLong(2);
                    // we only delete the items that expire in one week
                    if (dateExpires > expiredOneWeek) {
                        totalDeleteCount += delete(Files.getContentUri(volumeName, id), null, null);
                    } else {
                        final String oriPath = c.getString(3);

                        final boolean success = extendExpiredItem(db, oriPath, id, expiredTime,
                                expiredTime + index);
                        if (success) {
                            totalExtendedCount++;
                        }
                        index++;
                    }
                }
                return new int[]{totalDeleteCount, totalExtendedCount};
            }
        });
        return result;
    }

    /**
     * Extend the expired items by renaming the file to new path with new timestamp and updating the
     * database for {@link FileColumns#DATA} and {@link FileColumns#DATE_EXPIRES}. If there is
     * UNIQUE constraint error for FileColumns.DATA, use adjustedExpiredTime and generate the new
     * path by adjustedExpiredTime.
     */
    private boolean extendExpiredItem(@NonNull SQLiteDatabase db, @NonNull String originalPath,
            long id, long newExpiredTime, long adjustedExpiredTime) {
        String newPath = FileUtils.getAbsoluteExtendedPath(originalPath, newExpiredTime);
        if (newPath == null) {
            Log.e(TAG, "Couldn't compute path for " + originalPath + " and expired time "
                    + newExpiredTime);
            return false;
        }

        try {
            if (updateDatabaseForExpiredItem(db, newPath, id, newExpiredTime)) {
                return renameInLowerFsAndInvalidateFuseDentry(originalPath, newPath);
            }
            return false;
        } catch (SQLiteConstraintException e) {
            final String errorMessage =
                    "Update database _data from " + originalPath + " to " + newPath + " failed.";
            Log.d(TAG, errorMessage, e);
        }

        // When we update the database for newPath with newExpiredTime, if the new path already
        // exists in the database, it may raise SQLiteConstraintException.
        // If there are two expired items that have the same display name in the same directory,
        // but they have different expired time. E.g. .trashed-123-A.jpg and .trashed-456-A.jpg.
        // After we rename .trashed-123-A.jpg to .trashed-newExpiredTime-A.jpg, then we rename
        // .trashed-456-A.jpg to .trashed-newExpiredTime-A.jpg, it raises the exception. For
        // this case, we will retry it with the adjustedExpiredTime again.
        newPath = FileUtils.getAbsoluteExtendedPath(originalPath, adjustedExpiredTime);
        Log.i(TAG, "Retrying to extend expired item with the new path = " + newPath);
        try {
            if (updateDatabaseForExpiredItem(db, newPath, id, adjustedExpiredTime)) {
                return renameInLowerFsAndInvalidateFuseDentry(originalPath, newPath);
            }
        } catch (SQLiteConstraintException e) {
            // If we want to rename one expired item E.g. .trashed-123-A.jpg., and there is another
            // non-expired trashed/pending item has the same name. E.g.
            // .trashed-adjustedExpiredTime-A.jpg. When we rename .trashed-123-A.jpg to
            // .trashed-adjustedExpiredTime-A.jpg, it raises the SQLiteConstraintException.
            // The smallest unit of the expired time we use is second. It is a very rare case.
            // When this case is happened, we can handle it in next idle maintenance.
            final String errorMessage =
                    "Update database _data from " + originalPath + " to " + newPath + " failed.";
            Log.d(TAG, errorMessage, e);
        }

        return false;
    }

    private boolean updateDatabaseForExpiredItem(@NonNull SQLiteDatabase db,
            @NonNull String path, long id, long expiredTime) {
        final String table = "files";
        final String whereClause = MediaColumns._ID + "=?";
        final String[] whereArgs = new String[]{String.valueOf(id)};
        final ContentValues values = new ContentValues();
        values.put(FileColumns.DATA, path);
        values.put(FileColumns.DATE_EXPIRES, expiredTime);
        final int count = db.update(table, values, whereClause, whereArgs);
        return count == 1;
    }

    private boolean renameInLowerFsAndInvalidateFuseDentry(@NonNull String originalPath,
            @NonNull String newPath) {
        try {
            Os.rename(originalPath, newPath);
            invalidateFuseDentry(originalPath);
            invalidateFuseDentry(newPath);
            return true;
        } catch (ErrnoException e) {
            final String errorMessage = "Rename " + originalPath + " to " + newPath
                    + " in lower file system for extending item failed.";
            Log.e(TAG, errorMessage, e);
        }
        return false;
    }

    public void onIdleMaintenanceStopped() {
        mMediaScanner.onIdleScanStopped();
    }

    /**
     * Orphan any content of the given package. This will delete Android/media orphaned files from
     * the database.
     */
    public void onPackageOrphaned(String packageName, int uid) {
        mExternalDatabase.runWithTransaction((db) -> {
            final int userId = uid / PER_USER_RANGE;
            onPackageOrphaned(db, packageName, userId);
            return null;
        });
    }

    /**
     * Orphan any content of the given package from the given database. This will delete
     * Android/media files from the database if the underlying file no longe exists.
     */
    public void onPackageOrphaned(@NonNull SQLiteDatabase db,
            @NonNull String packageName, int userId) {
        // Delete Android/media entries.
        deleteAndroidMediaEntries(db, packageName, userId);
        // Orphan rest of entries.
        orphanEntries(db, packageName, userId);
    }

    private void deleteAndroidMediaEntries(SQLiteDatabase db, String packageName, int userId) {
        String relativePath = "Android/media/" + DatabaseUtils.escapeForLike(packageName) + "/%";
        try (Cursor cursor = db.query(
                "files",
                new String[] { MediaColumns._ID, MediaColumns.DATA },
                "relative_path LIKE ? ESCAPE '\\' AND owner_package_name=? AND _user_id=?",
                new String[] { relativePath, packageName, "" + userId },
                /* groupBy= */ null,
                /* having= */ null,
                /* orderBy= */null,
                /* limit= */ null)) {
            int countDeleted = 0;
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    File file = new File(cursor.getString(1));
                    // We check for existence to be sure we don't delete files that still exist.
                    // This can happen even if the pair (package, userid) is unknown,
                    // since some framework implementations may rely on special userids.
                    if (!file.exists()) {
                        countDeleted +=
                                db.delete("files", "_id=?", new String[]{cursor.getString(0)});
                    }
                }
            }
            Log.d(TAG, "Deleted " + countDeleted + " Android/media items belonging to "
                    + packageName + " on " + db.getPath());
        }
    }

    private void orphanEntries(
            @NonNull SQLiteDatabase db, @NonNull String packageName, int userId) {
        final ContentValues values = new ContentValues();
        values.putNull(FileColumns.OWNER_PACKAGE_NAME);

        final int countOrphaned = db.update("files", values,
                "owner_package_name=? AND _user_id=?", new String[] { packageName, "" + userId });
        if (countOrphaned > 0) {
            Log.d(TAG, "Orphaned " + countOrphaned + " items belonging to "
                    + packageName + " on " + db.getPath());
        }
    }

    public void scanDirectory(File file, int reason) {
        mMediaScanner.scanDirectory(file, reason);
    }

    public Uri scanFile(File file, int reason) {
        return scanFile(file, reason, null);
    }

    public Uri scanFile(File file, int reason, String ownerPackage) {
        return mMediaScanner.scanFile(file, reason, ownerPackage);
    }

    private Uri scanFileAsMediaProvider(File file, int reason) {
        final LocalCallingIdentity tokenInner = clearLocalCallingIdentity();
        try {
            return scanFile(file, REASON_DEMAND);
        } finally {
            restoreLocalCallingIdentity(tokenInner);
        }
    }

    /**
     * Called when a new file is created through FUSE
     *
     * @param file path of the file that was created
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public void onFileCreatedForFuse(String path) {
        // Make sure we update the quota type of the file
        BackgroundThread.getExecutor().execute(() -> {
            File file = new File(path);
            int mediaType = MimeUtils.resolveMediaType(MimeUtils.resolveMimeType(file));
            updateQuotaTypeForFileInternal(file, mediaType);
        });
    }

    private boolean isAppCloneUserPair(int userId1, int userId2) {
        UserHandle user1 = UserHandle.of(userId1);
        UserHandle user2 = UserHandle.of(userId2);
        if (SdkLevel.isAtLeastS()) {
            if (mUserCache.userSharesMediaWithParent(user1)
                    || mUserCache.userSharesMediaWithParent(user2)) {
                return true;
            }
            if (Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.S) {
                // If we're on S or higher, and we shipped with S or higher, only allow the new
                // app cloning functionality
                return false;
            }
            // else, fall back to deprecated solution below on updating devices
        }
        try {
            Method isAppCloneUserPair = StorageManager.class.getMethod("isAppCloneUserPair",
                int.class, int.class);
            return (Boolean) isAppCloneUserPair.invoke(mStorageManager, userId1, userId2);
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            Log.w(TAG, "isAppCloneUserPair failed. Users: " + userId1 + " and " + userId2);
            return false;
        }
    }

    /**
     * Determines whether the passed in userId forms an app clone user pair with user 0.
     *
     * @param userId user ID to check
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public boolean isAppCloneUserForFuse(int userId) {
        if (!isCrossUserEnabled()) {
            Log.d(TAG, "CrossUser not enabled.");
            return false;
        }
        boolean result = isAppCloneUserPair(0, userId);

        Log.w(TAG, "isAppCloneUserPair for user " + userId + ": " + result);

        return result;
    }

    /**
     * Determines if to allow FUSE_LOOKUP for uid. Might allow uids that don't belong to the
     * MediaProvider user, depending on OEM configuration.
     *
     * @param uid linux uid to check
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public boolean shouldAllowLookupForFuse(int uid, int pathUserId) {
        int callingUserId = uidToUserId(uid);
        if (!isCrossUserEnabled()) {
            Log.d(TAG, "CrossUser not enabled. Users: " + callingUserId + " and " + pathUserId);
            return false;
        }

        if (callingUserId != pathUserId && callingUserId != 0 && pathUserId != 0) {
            Log.w(TAG, "CrossUser at least one user is 0 check failed. Users: " + callingUserId
                    + " and " + pathUserId);
            return false;
        }

        if (mUserCache.isWorkProfile(callingUserId) || mUserCache.isWorkProfile(pathUserId)) {
            // Cross-user lookup not allowed if one user in the pair has a profile owner app
            Log.w(TAG, "CrossUser work profile check failed. Users: " + callingUserId + " and "
                    + pathUserId);
            return false;
        }

        boolean result = isAppCloneUserPair(pathUserId, callingUserId);
        if (result) {
            Log.i(TAG, "CrossUser allowed. Users: " + callingUserId + " and " + pathUserId);
        } else {
            Log.w(TAG, "CrossUser isAppCloneUserPair check failed. Users: " + callingUserId
                    + " and " + pathUserId);
        }

        return result;
    }

    /**
     * Called from FUSE to transform a file
     *
     * A transform can change the file contents for {@code uid} from {@code src} to {@code dst}
     * depending on {@code flags}. This allows the FUSE daemon serve different file contents for
     * the same file to different apps.
     *
     * The only supported transform for now is transcoding which re-encodes a file taken in a modern
     * format like HEVC to a legacy format like AVC.
     *
     * @param src file path to transform
     * @param dst file path to save transformed file
     * @param flags determines the kind of transform
     * @param readUid app that called us requesting transform
     * @param openUid app that originally made the open call
     * @param mediaCapabilitiesUid app for which the transform decision was made,
     *                             0 if decision was made with openUid
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public boolean transformForFuse(String src, String dst, int transforms, int transformsReason,
            int readUid, int openUid, int mediaCapabilitiesUid) {
        if ((transforms & FLAG_TRANSFORM_TRANSCODING) != 0) {
            if (mTranscodeHelper.isTranscodeFileCached(src, dst)) {
                Log.d(TAG, "Using transcode cache for " + src);
                return true;
            }

            // In general we always mark the opener as causing transcoding.
            // However, if the mediaCapabilitiesUid is available then we mark the reader as causing
            // transcoding.  This handles the case where a malicious app might want to take
            // advantage of mediaCapabilitiesUid by setting it to another app's uid and reading the
            // media contents itself; in such cases we'd mark the reader (malicious app) for the
            // cost of transcoding.
            //
            //                     openUid             readUid                mediaCapabilitiesUid
            // -------------------------------------------------------------------------------------
            // using picker         SAF                 app                           app
            // abusive case        bad app             bad app                       victim
            // modern to lega-
            // -cy sharing         modern              legacy                        legacy
            //
            // we'd not be here in the below case.
            // legacy to mode-
            // -rn sharing         legacy              modern                        modern

            int transcodeUid = openUid;
            if (mediaCapabilitiesUid > 0) {
                Log.d(TAG, "Fix up transcodeUid to " + readUid + ". openUid " + openUid
                        + ", mediaCapabilitiesUid " + mediaCapabilitiesUid);
                transcodeUid = readUid;
            }
            return mTranscodeHelper.transcode(src, dst, transcodeUid, transformsReason);
        }
        return true;
    }

    /**
     * Called from FUSE to get {@link FileLookupResult} for a {@code path} and {@code uid}
     *
     * {@link FileLookupResult} contains transforms, transforms completion status and ioPath
     * for transform lookup query for a file and uid.
     *
     * @param path file path to get transforms for
     * @param uid app requesting IO form kernel
     * @param tid FUSE thread id handling IO request from kernel
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public FileLookupResult onFileLookupForFuse(String path, int uid, int tid) {
        uid = getBinderUidForFuse(uid, tid);
        final int userId = uidToUserId(uid);

        if (isSyntheticPath(path, userId)) {
            if (isRedactedPath(path, userId)) {
                return handleRedactedFileLookup(uid, path);
            } else if (isPickerPath(path, userId)) {
                return handlePickerFileLookup(userId, uid, path);
            }

            throw new IllegalStateException("Unexpected synthetic path: " + path);
        }

        if (mTranscodeHelper.supportsTranscode(path)) {
            return handleTranscodedFileLookup(path, uid, tid);
        }

        return new FileLookupResult(/* transforms */ 0, uid, /* ioPath */ "");
    }

    private FileLookupResult handleTranscodedFileLookup(String path, int uid, int tid) {
        final int transformsReason;
        final PendingOpenInfo info;

        synchronized (mPendingOpenInfo) {
            info = mPendingOpenInfo.get(tid);
        }

        if (info != null && info.uid == uid) {
            transformsReason = info.transcodeReason;
        } else {
            transformsReason = mTranscodeHelper.shouldTranscode(path, uid, null /* bundle */);
        }

        if (transformsReason > 0) {
            final String ioPath = mTranscodeHelper.prepareIoPath(path, uid);
            final boolean transformsComplete = mTranscodeHelper.isTranscodeFileCached(path, ioPath);

            return new FileLookupResult(FLAG_TRANSFORM_TRANSCODING, transformsReason, uid,
                    transformsComplete, /* transformsSupported */ true, ioPath);
        }

        return new FileLookupResult(/* transforms */ 0, transformsReason, uid,
                /* transformsComplete */ true, /* transformsSupported */ true, "");
    }

    private FileLookupResult handleRedactedFileLookup(int uid, @NonNull String path) {
        final LocalCallingIdentity token = clearLocalCallingIdentity();
        final String fileName = extractFileName(path);

        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(FileUtils.getContentUriForPath(path));
        } catch (VolumeNotFoundException e) {
            throw new IllegalStateException("Volume not found for file: " + path);
        }

        try (final Cursor c = helper.runWithoutTransaction(
                (db) -> db.query("files", new String[]{MediaColumns.DATA},
                        FileColumns.REDACTED_URI_ID + "=?", new String[]{fileName}, null, null,
                        null))) {
            if (c.moveToFirst()) {
                return new FileLookupResult(FLAG_TRANSFORM_REDACTION, uid, c.getString(0));
            }

            throw new IllegalStateException("Failed to fetch synthetic redacted path: " + path);
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    private FileLookupResult handlePickerFileLookup(int userId, int uid, @NonNull String path) {
        final File file = new File(path);
        final List<String> syntheticRelativePathSegments =
                extractSyntheticRelativePathSegements(path, userId);
        final int segmentCount = syntheticRelativePathSegments.size();

        if (segmentCount < 1 || segmentCount > 5) {
            throw new IllegalStateException("Unexpected synthetic picker path: " + file);
        }

        final String lastSegment = syntheticRelativePathSegments.get(segmentCount - 1);

        boolean result = false;
        switch (segmentCount) {
            case 1:
                // .../picker
                if (lastSegment.equals("picker")) {
                    result = file.exists() || file.mkdir();
                }
                break;
            case 2:
                // .../picker/<user-id>
                try {
                    Integer.parseInt(lastSegment);
                    result = file.exists() || file.mkdir();
                } catch (NumberFormatException e) {
                    Log.w(TAG, "Invalid user id for picker file lookup: " + lastSegment
                            + ". File: " + file);
                }
                break;
            case 3:
                // .../picker/<user-id>/<authority>
                result = preparePickerAuthorityPathSegment(file, lastSegment, uid);
                break;
            case 4:
                // .../picker/<user-id>/<authority>/media
                if (lastSegment.equals("media")) {
                    result = file.exists() || file.mkdir();
                }
                break;
            case 5:
                // .../picker/<user-id>/<authority>/media/<media-id.extension>
                final String fileUserId = syntheticRelativePathSegments.get(1);
                final String authority = syntheticRelativePathSegments.get(2);
                result = preparePickerMediaIdPathSegment(file, authority, lastSegment, fileUserId);
                break;
        }

        if (result) {
            return new FileLookupResult(FLAG_TRANSFORM_PICKER, uid, path);
        }
        throw new IllegalStateException("Failed to prepare synthetic picker path: " + file);
    }

    private FileOpenResult handlePickerFileOpen(String path, int uid) {
        final String[] segments = path.split("/");
        if (segments.length != 11) {
            Log.e(TAG, "Picker file open failed. Unexpected segments: " + path);
            return new FileOpenResult(OsConstants.ENOENT /* status */, uid, /* transformsUid */ 0,
                    new long[0]);
        }

        // ['', 'storage', 'emulated', '0', 'transforms', 'synthetic', 'picker', '<user-id>',
        // '<host>', 'media', '<fileName>']
        final String userId = segments[7];
        final String fileName = segments[10];
        final String host = segments[8];
        final String authority = userId + "@" + host;
        final int lastDotIndex = fileName.lastIndexOf('.');

        if (lastDotIndex == -1) {
            Log.e(TAG, "Picker file open failed. No file extension: " + path);
            return FileOpenResult.createError(OsConstants.ENOENT, uid);
        }

        final String mediaId = fileName.substring(0, lastDotIndex);
        final Uri uri = getMediaUri(authority).buildUpon().appendPath(mediaId).build();

        IBinder binder = getContext().getContentResolver()
                .call(uri, METHOD_GET_ASYNC_CONTENT_PROVIDER, null, null)
                .getBinder(EXTRA_ASYNC_CONTENT_PROVIDER);
        if (binder == null) {
            Log.e(TAG, "Picker file open failed. No cloud media provider found.");
            return FileOpenResult.createError(OsConstants.ENOENT, uid);
        }
        IAsyncContentProvider iAsyncContentProvider = IAsyncContentProvider.Stub.asInterface(
                binder);
        AsyncContentProvider asyncContentProvider = new AsyncContentProvider(iAsyncContentProvider);
        final ParcelFileDescriptor pfd;
        try {
            pfd = asyncContentProvider.openMedia(uri, "r");
        } catch (FileNotFoundException | ExecutionException | InterruptedException
                | TimeoutException | RemoteException e) {
            Log.e(TAG, "Picker file open failed. Failed to open URI: " + uri, e);
            return FileOpenResult.createError(OsConstants.ENOENT, uid);
        }

        try (FileInputStream fis = new FileInputStream(pfd.getFileDescriptor())) {
            final String mimeType = MimeUtils.resolveMimeType(new File(path));
            final long[] redactionRanges = getRedactionRanges(fis, mimeType).redactionRanges;
            return new FileOpenResult(0 /* status */, uid, /* transformsUid */ 0,
                    /* nativeFd */ pfd.detachFd(), redactionRanges);
        } catch (IOException e) {
            Log.e(TAG, "Picker file open failed. No file extension: " + path, e);
            return FileOpenResult.createError(OsConstants.ENOENT, uid);
        }
    }

    private boolean preparePickerAuthorityPathSegment(File file, String authority, int uid) {
        if (mPickerSyncController.isProviderEnabled(authority)) {
            return file.exists() || file.mkdir();
        }

        return false;
    }

    private boolean preparePickerMediaIdPathSegment(File file, String authority, String fileName,
            String userId) {
        final String mediaId = extractFileName(fileName);
        final String[] projection = new String[] { MediaStore.PickerMediaColumns.SIZE };

        final Uri uri = Uri.parse("content://media/picker/" + userId + "/" + authority + "/media/"
                + mediaId);
        try (Cursor cursor =  mPickerUriResolver.query(uri, projection, /* callingUid */0,
                android.os.Process.myUid())) {
            if (cursor != null && cursor.moveToFirst()) {
                final int sizeBytesIdx = cursor.getColumnIndex(MediaStore.PickerMediaColumns.SIZE);

                if (sizeBytesIdx != -1) {
                    return createSparseFile(file, cursor.getLong(sizeBytesIdx));
                }
            }
        }

        return false;
    }

    public int getBinderUidForFuse(int uid, int tid) {
        if (uid != MY_UID) {
            return uid;
        }

        synchronized (mPendingOpenInfo) {
            PendingOpenInfo info = mPendingOpenInfo.get(tid);
            if (info == null) {
                return uid;
            }
            return info.uid;
        }
    }

    private static int uidToUserId(int uid) {
        return uid / PER_USER_RANGE;
    }

    /**
     * Returns true if the app denoted by the given {@code uid} and {@code packageName} is allowed
     * to clear other apps' cache directories.
     */
    static boolean hasPermissionToClearCaches(Context context, ApplicationInfo ai) {
        PermissionUtils.setOpDescription("clear app cache");
        try {
            return PermissionUtils.checkPermissionManager(context, /* pid */ -1, ai.uid,
                    ai.packageName, /* attributionTag */ null);
        } finally {
            PermissionUtils.clearOpDescription();
        }
    }

    @VisibleForTesting
    void computeAudioLocalizedValues(ContentValues values) {
        try {
            final String title = values.getAsString(AudioColumns.TITLE);
            final String titleRes = values.getAsString(AudioColumns.TITLE_RESOURCE_URI);

            if (!TextUtils.isEmpty(titleRes)) {
                final String localized = getLocalizedTitle(titleRes);
                if (!TextUtils.isEmpty(localized)) {
                    values.put(AudioColumns.TITLE, localized);
                }
            } else {
                final String localized = getLocalizedTitle(title);
                if (!TextUtils.isEmpty(localized)) {
                    values.put(AudioColumns.TITLE, localized);
                    values.put(AudioColumns.TITLE_RESOURCE_URI, title);
                }
            }
        } catch (Exception e) {
            Log.w(TAG, "Failed to localize title", e);
        }
    }

    @VisibleForTesting
    static void computeAudioKeyValues(ContentValues values) {
        computeAudioKeyValue(values, AudioColumns.TITLE, AudioColumns.TITLE_KEY, /* focusId */
                null, /* hashValue */ 0);
        computeAudioKeyValue(values, AudioColumns.ARTIST, AudioColumns.ARTIST_KEY,
                AudioColumns.ARTIST_ID, /* hashValue */ 0);
        computeAudioKeyValue(values, AudioColumns.GENRE, AudioColumns.GENRE_KEY,
                AudioColumns.GENRE_ID, /* hashValue */ 0);
        computeAudioAlbumKeyValue(values);
    }

    /**
     * To distinguish same-named albums, we append a hash. The hash is
     * based on the "album artist" tag if present, otherwise on the path of
     * the parent directory of the audio file.
     */
    private static void computeAudioAlbumKeyValue(ContentValues values) {
        int hashCode = 0;

        final String albumArtist = values.getAsString(MediaColumns.ALBUM_ARTIST);
        if (!TextUtils.isEmpty(albumArtist)) {
            hashCode = albumArtist.hashCode();
        } else {
            final String path = values.getAsString(MediaColumns.DATA);
            if (!TextUtils.isEmpty(path)) {
                hashCode = path.substring(0, path.lastIndexOf('/')).hashCode();
            }
        }

        computeAudioKeyValue(values, AudioColumns.ALBUM, AudioColumns.ALBUM_KEY,
                AudioColumns.ALBUM_ID, hashCode);
    }

    private static void computeAudioKeyValue(@NonNull ContentValues values, @NonNull String focus,
            @Nullable String focusKey, @Nullable String focusId, int hashValue) {
        if (focusKey != null) values.remove(focusKey);
        if (focusId != null) values.remove(focusId);

        final String value = values.getAsString(focus);
        if (TextUtils.isEmpty(value)) return;

        final String key = Audio.keyFor(value);
        if (key == null) return;

        if (focusKey != null) {
            values.put(focusKey, key);
        }
        if (focusId != null) {
            // Many apps break if we generate negative IDs, so trim off the
            // highest bit to ensure we're always unsigned
            final long id = Hashing.farmHashFingerprint64().hashString(key + hashValue,
                    StandardCharsets.UTF_8).asLong() & ~(1L << 63);
            values.put(focusId, id);
        }
    }

    @Override
    public Uri canonicalize(Uri uri) {
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        // Skip when we have nothing to canonicalize
        if ("1".equals(uri.getQueryParameter(CANONICAL))) {
            return uri;
        }

        try (Cursor c = queryForSingleItem(uri, null, null, null, null)) {
            switch (match) {
                case AUDIO_MEDIA_ID: {
                    final String title = getDefaultTitleFromCursor(c);
                    if (!TextUtils.isEmpty(title)) {
                        final Uri.Builder builder = uri.buildUpon();
                        builder.appendQueryParameter(AudioColumns.TITLE, title);
                        builder.appendQueryParameter(CANONICAL, "1");
                        return builder.build();
                    }
                    break;
                }
                case VIDEO_MEDIA_ID:
                case IMAGES_MEDIA_ID: {
                    final String documentId = c
                            .getString(c.getColumnIndexOrThrow(MediaColumns.DOCUMENT_ID));
                    if (!TextUtils.isEmpty(documentId)) {
                        final Uri.Builder builder = uri.buildUpon();
                        builder.appendQueryParameter(MediaColumns.DOCUMENT_ID, documentId);
                        builder.appendQueryParameter(CANONICAL, "1");
                        return builder.build();
                    }
                    break;
                }
            }
        } catch (FileNotFoundException e) {
            Log.w(TAG, e.getMessage());
        }
        return null;
    }

    @Override
    public Uri uncanonicalize(Uri uri) {
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        // Skip when we have nothing to uncanonicalize
        if (!"1".equals(uri.getQueryParameter(CANONICAL))) {
            return uri;
        }

        // Extract values and then clear to avoid recursive lookups
        final String title = uri.getQueryParameter(AudioColumns.TITLE);
        final String documentId = uri.getQueryParameter(MediaColumns.DOCUMENT_ID);
        uri = uri.buildUpon().clearQuery().build();

        switch (match) {
            case AUDIO_MEDIA_ID: {
                // First check for an exact match
                try (Cursor c = queryForSingleItem(uri, null, null, null, null)) {
                    if (Objects.equals(title, getDefaultTitleFromCursor(c))) {
                        return uri;
                    }
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Trouble resolving " + uri + "; falling back to search: " + e);
                }

                // Otherwise fallback to searching
                final Uri baseUri = ContentUris.removeId(uri);
                try (Cursor c = queryForSingleItem(baseUri,
                        new String[] { BaseColumns._ID },
                        AudioColumns.TITLE + "=?", new String[] { title }, null)) {
                    return ContentUris.withAppendedId(baseUri, c.getLong(0));
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Failed to resolve " + uri + ": " + e);
                    return null;
                }
            }
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID: {
                // First check for an exact match
                try (Cursor c = queryForSingleItem(uri, null, null, null, null)) {
                    if (Objects.equals(title, getDefaultTitleFromCursor(c))) {
                        return uri;
                    }
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Trouble resolving " + uri + "; falling back to search: " + e);
                }

                // Otherwise fallback to searching
                final Uri baseUri = ContentUris.removeId(uri);
                try (Cursor c = queryForSingleItem(baseUri,
                        new String[] { BaseColumns._ID },
                        MediaColumns.DOCUMENT_ID + "=?", new String[] { documentId }, null)) {
                    return ContentUris.withAppendedId(baseUri, c.getLong(0));
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Failed to resolve " + uri + ": " + e);
                    return null;
                }
            }
        }

        return uri;
    }

    private Uri safeUncanonicalize(Uri uri) {
        Uri newUri = uncanonicalize(uri);
        if (newUri != null) {
            return newUri;
        }
        return uri;
    }

    /**
     * @return where clause to exclude database rows where
     * <ul>
     * <li> {@code column} is set or
     * <li> {@code column} is {@link MediaColumns#IS_PENDING} and is set by FUSE and not owned by
     * calling package.
     * <li> {@code column} is {@link MediaColumns#IS_PENDING}, is unset and is waiting for
     * metadata update from a deferred scan.
     * </ul>
     */
    private String getWhereClauseForMatchExclude(@NonNull String column) {
        if (column.equalsIgnoreCase(MediaColumns.IS_PENDING)) {
            // Don't include rows that are pending for metadata
            final String pendingForMetadata = FileColumns._MODIFIER + "="
                    + FileColumns._MODIFIER_CR_PENDING_METADATA;
            final String notPending = String.format("(%s=0 AND NOT %s)", column,
                    pendingForMetadata);
            final String matchSharedPackagesClause = FileColumns.OWNER_PACKAGE_NAME + " IN "
                    + getSharedPackages();
            // Include owned pending files from Fuse
            final String pendingFromFuse = String.format("(%s=1 AND %s AND %s)", column,
                    MATCH_PENDING_FROM_FUSE, matchSharedPackagesClause);
            return "(" + notPending + " OR " + pendingFromFuse + ")";
        }
        return column + "=0";
    }

    /**
     * @return where clause to include database rows where
     * <ul>
     * <li> {@code column} is not set or
     * <li> {@code column} is set and calling package has write permission to corresponding db row
     *      or {@code column} is {@link MediaColumns#IS_PENDING} and is set by FUSE.
     * </ul>
     * The method is used to match db rows corresponding to writable pending and trashed files.
     */
    @Nullable
    private String getWhereClauseForMatchableVisibleFromFilePath(@NonNull Uri uri,
            @NonNull String column) {
        if (isCallingPackageLegacyWrite() || checkCallingPermissionGlobal(uri, /*forWrite*/ true)) {
            // No special filtering needed
            return null;
        }

        final String callingPackage = getCallingPackageOrSelf();

        final ArrayList<String> options = new ArrayList<>();
        switch(matchUri(uri, isCallingPackageAllowedHidden())) {
            case IMAGES_MEDIA_ID:
            case IMAGES_MEDIA:
            case IMAGES_THUMBNAILS_ID:
            case IMAGES_THUMBNAILS:
                if (checkCallingPermissionImages(/*forWrite*/ true, callingPackage)) {
                    // No special filtering needed
                    return null;
                }
                break;
            case AUDIO_MEDIA_ID:
            case AUDIO_MEDIA:
            case AUDIO_PLAYLISTS_ID:
            case AUDIO_PLAYLISTS:
                if (checkCallingPermissionAudio(/*forWrite*/ true, callingPackage)) {
                    // No special filtering needed
                    return null;
                }
                break;
            case VIDEO_MEDIA_ID:
            case VIDEO_MEDIA:
            case VIDEO_THUMBNAILS_ID:
            case VIDEO_THUMBNAILS:
                if (checkCallingPermissionVideo(/*firWrite*/ true, callingPackage)) {
                    // No special filtering needed
                    return null;
                }
                break;
            case DOWNLOADS_ID:
            case DOWNLOADS:
                // No app has special permissions for downloads.
                break;
            case FILES_ID:
            case FILES:
                if (checkCallingPermissionAudio(/*forWrite*/ true, callingPackage)) {
                    // Allow apps with audio permission to include audio* media types.
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_AUDIO));
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_PLAYLIST));
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_SUBTITLE));
                }
                if (checkCallingPermissionVideo(/*forWrite*/ true, callingPackage)) {
                    // Allow apps with video permission to include video* media types.
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_VIDEO));
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_SUBTITLE));
                }
                if (checkCallingPermissionImages(/*forWrite*/ true, callingPackage)) {
                    // Allow apps with images permission to include images* media types.
                    options.add(DatabaseUtils.bindSelection("media_type=?",
                            FileColumns.MEDIA_TYPE_IMAGE));
                }
                break;
            default:
                // is_pending, is_trashed are not applicable for rest of the media tables.
                return null;
        }

        final String matchSharedPackagesClause = FileColumns.OWNER_PACKAGE_NAME + " IN "
                + getSharedPackages();
        options.add(DatabaseUtils.bindSelection(matchSharedPackagesClause));

        if (column.equalsIgnoreCase(MediaColumns.IS_PENDING)) {
            // Include all pending files from Fuse
            options.add(MATCH_PENDING_FROM_FUSE);
        }

        final String matchWritableRowsClause = String.format("%s=0 OR (%s=1 AND %s)", column,
                column, TextUtils.join(" OR ", options));
        return matchWritableRowsClause;
    }

    /**
     * Gets list of files in {@code path} from media provider database.
     *
     * @param path path of the directory.
     * @param uid UID of the calling process.
     * @return a list of file names in the given directory path.
     * An empty list is returned if no files are visible to the calling app or the given directory
     * does not have any files.
     * A list with ["/"] is returned if the path is not indexed by MediaProvider database or
     * calling package is a legacy app and has appropriate storage permissions for the given path.
     * In both scenarios file names should be obtained from lower file system.
     * A list with empty string[""] is returned if the calling package doesn't have access to the
     * given path.
     *
     * <p>Directory names are always obtained from lower file system.
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public String[] getFilesInDirectoryForFuse(String path, int uid) {
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), path);

        try {
            if (isPrivatePackagePathNotAccessibleByCaller(path)) {
                return new String[] {""};
            }

            if (shouldBypassFuseRestrictions(/*forWrite*/ false, path)) {
                return new String[] {"/"};
            }

            // Do not allow apps to list Android/data or Android/obb dirs.
            // On primary volumes, apps that get special access to these directories get it via
            // mount views of lowerfs. On secondary volumes, such apps would return early from
            // shouldBypassFuseRestrictions above.
            if (isDataOrObbPath(path)) {
                return new String[] {""};
            }

            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (isCallingPackageRequestingLegacy()) {
                return new String[] {""};
            }

            // Get relative path for the contents of given directory.
            String relativePath = extractRelativePathWithDisplayName(path);

            if (relativePath == null) {
                // Path is /storage/emulated/, if relativePath is null, MediaProvider doesn't
                // have any details about the given directory. Use lower file system to obtain
                // files and directories in the given directory.
                return new String[] {"/"};
            }

            // For all other paths, get file names from media provider database.
            // Return media and non-media files visible to the calling package.
            ArrayList<String> fileNamesList = new ArrayList<>();

            // Only FileColumns.DATA contains actual name of the file.
            String[] projection = {MediaColumns.DATA};

            Bundle queryArgs = new Bundle();
            queryArgs.putString(QUERY_ARG_SQL_SELECTION, MediaColumns.RELATIVE_PATH +
                    " =? and mime_type not like 'null'");
            queryArgs.putStringArray(QUERY_ARG_SQL_SELECTION_ARGS, new String[] {relativePath});
            // Get database entries for files from MediaProvider database with
            // MediaColumns.RELATIVE_PATH as the given path.
            try (final Cursor cursor = query(FileUtils.getContentUriForPath(path), projection,
                    queryArgs, null)) {
                while(cursor.moveToNext()) {
                    fileNamesList.add(extractDisplayName(cursor.getString(0)));
                }
            }
            return fileNamesList.toArray(new String[fileNamesList.size()]);
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    /**
     * Scan files during directory renames for the following reasons:
     * <ul>
     * <li>Because we don't update db rows for directories, we scan the oldPath to discard stale
     * directory db rows. This prevents conflicts during subsequent db operations with oldPath.
     * <li>We need to scan newPath as well, because the new directory may have become hidden
     * or unhidden, in which case we need to update the media types of the contained files
     * </ul>
     */
    private void scanRenamedDirectoryForFuse(@NonNull String oldPath, @NonNull String newPath) {
        scanFileAsMediaProvider(new File(oldPath), REASON_DEMAND);
        scanFileAsMediaProvider(new File(newPath), REASON_DEMAND);
    }

    /**
     * Checks if given {@code mimeType} is supported in {@code path}.
     */
    private boolean isMimeTypeSupportedInPath(String path, String mimeType) {
        final String supportedPrimaryMimeType;
        final int match = matchUri(getContentUriForFile(path, mimeType), true);
        switch (match) {
            case AUDIO_MEDIA:
                supportedPrimaryMimeType = "audio";
                break;
            case VIDEO_MEDIA:
                supportedPrimaryMimeType = "video";
                break;
            case IMAGES_MEDIA:
                supportedPrimaryMimeType = "image";
                break;
            default:
                supportedPrimaryMimeType = ClipDescription.MIMETYPE_UNKNOWN;
        }
        return (supportedPrimaryMimeType.equalsIgnoreCase(ClipDescription.MIMETYPE_UNKNOWN) ||
                StringUtils.startsWithIgnoreCase(mimeType, supportedPrimaryMimeType));
    }

    /**
     * Removes owner package for the renamed path if the calling package doesn't own the db row
     *
     * When oldPath is renamed to newPath, if newPath exists in the database, and caller is not the
     * owner of the file, owner package is set to 'null'. This prevents previous owner of newPath
     * from accessing renamed file.
     * @return {@code true} if
     * <ul>
     * <li> there is no corresponding database row for given {@code path}
     * <li> shared calling package is the owner of the database row
     * <li> owner package name is already set to 'null'
     * <li> updating owner package name to 'null' was successful.
     * </ul>
     * Returns {@code false} otherwise.
     */
    private boolean maybeRemoveOwnerPackageForFuseRename(@NonNull DatabaseHelper helper,
            @NonNull String path) {

        final Uri uri = FileUtils.getContentUriForPath(path);
        final int match = matchUri(uri, isCallingPackageAllowedHidden());
        final String ownerPackageName;
        final String selection = MediaColumns.DATA + " =? AND "
                + MediaColumns.OWNER_PACKAGE_NAME + " != 'null'";
        final String[] selectionArgs = new String[] {path};

        final SQLiteQueryBuilder qbForQuery =
                getQueryBuilder(TYPE_QUERY, match, uri, Bundle.EMPTY, null);
        try (Cursor c = qbForQuery.query(helper, new String[] {FileColumns.OWNER_PACKAGE_NAME},
                selection, selectionArgs, null, null, null, null, null)) {
            if (!c.moveToFirst()) {
                // We don't need to remove owner_package from db row if path doesn't exist in
                // database or owner_package is already set to 'null'
                return true;
            }
            ownerPackageName = c.getString(0);
            if (isCallingIdentitySharedPackageName(ownerPackageName)) {
                // We don't need to remove owner_package from db row if calling package is the owner
                // of the database row
                return true;
            }
        }

        final SQLiteQueryBuilder qbForUpdate =
                getQueryBuilder(TYPE_UPDATE, match, uri, Bundle.EMPTY, null);
        ContentValues values = new ContentValues();
        values.put(FileColumns.OWNER_PACKAGE_NAME, "null");
        return qbForUpdate.update(helper, values, selection, selectionArgs) == 1;
    }

    private boolean updateDatabaseForFuseRename(@NonNull DatabaseHelper helper,
            @NonNull String oldPath, @NonNull String newPath, @NonNull ContentValues values) {
        return updateDatabaseForFuseRename(helper, oldPath, newPath, values, Bundle.EMPTY);
    }

    private boolean updateDatabaseForFuseRename(@NonNull DatabaseHelper helper,
            @NonNull String oldPath, @NonNull String newPath, @NonNull ContentValues values,
            @NonNull Bundle qbExtras) {
        return updateDatabaseForFuseRename(helper, oldPath, newPath, values, qbExtras,
                FileUtils.getContentUriForPath(oldPath));
    }

    /**
     * Updates database entry for given {@code path} with {@code values}
     */
    private boolean updateDatabaseForFuseRename(@NonNull DatabaseHelper helper,
            @NonNull String oldPath, @NonNull String newPath, @NonNull ContentValues values,
            @NonNull Bundle qbExtras, Uri uriOldPath) {
        boolean allowHidden = isCallingPackageAllowedHidden();
        final SQLiteQueryBuilder qbForUpdate = getQueryBuilder(TYPE_UPDATE,
                matchUri(uriOldPath, allowHidden), uriOldPath, qbExtras, null);
        if (values.containsKey(FileColumns._MODIFIER)) {
            qbForUpdate.allowColumn(FileColumns._MODIFIER);
        }
        final String selection = MediaColumns.DATA + " =? ";
        int count = 0;
        boolean retryUpdateWithReplace = false;

        try {
            // TODO(b/146777893): System gallery apps can rename a media directory containing
            // non-media files. This update doesn't support updating non-media files that are not
            // owned by system gallery app.
            count = qbForUpdate.update(helper, values, selection, new String[]{oldPath});
        } catch (SQLiteConstraintException e) {
            Log.w(TAG, "Database update failed while renaming " + oldPath, e);
            retryUpdateWithReplace = true;
        }

        if (retryUpdateWithReplace) {
            if (deleteForFuseRename(helper, oldPath, newPath, qbExtras, selection, allowHidden)) {
                Log.i(TAG, "Retrying database update after deleting conflicting entry");
                count = qbForUpdate.update(helper, values, selection, new String[]{oldPath});
            } else {
                return false;
            }
        }
        return count == 1;
    }

    private boolean deleteForFuseRename(DatabaseHelper helper, String oldPath,
            String newPath, Bundle qbExtras, String selection, boolean allowHidden) {
        // We are replacing file in newPath with file in oldPath. If calling package has
        // write permission for newPath, delete existing database entry and retry update.
        final Uri uriNewPath = FileUtils.getContentUriForPath(oldPath);
        final SQLiteQueryBuilder qbForDelete = getQueryBuilder(TYPE_DELETE,
                matchUri(uriNewPath, allowHidden), uriNewPath, qbExtras, null);
        if (qbForDelete.delete(helper, selection, new String[] {newPath}) == 1) {
            return true;
        }
        // Check if delete can be done using other URI grants
        final String[] projection = new String[] {
                FileColumns.MEDIA_TYPE,
                FileColumns.DATA,
                FileColumns._ID,
                FileColumns.IS_DOWNLOAD,
                FileColumns.MIME_TYPE,
        };
        return
            deleteWithOtherUriGrants(
                    FileUtils.getContentUriForPath(newPath),
                    helper, projection, selection, new String[] {newPath}, qbExtras) == 1;
    }

    /**
     * Gets {@link ContentValues} for updating database entry to {@code path}.
     */
    private ContentValues getContentValuesForFuseRename(String path, String newMimeType,
            boolean wasHidden, boolean isHidden, boolean isSameMimeType) {
        ContentValues values = new ContentValues();
        values.put(MediaColumns.MIME_TYPE, newMimeType);
        values.put(MediaColumns.DATA, path);

        if (isHidden) {
            values.put(FileColumns.MEDIA_TYPE, FileColumns.MEDIA_TYPE_NONE);
        } else {
            int mediaType = MimeUtils.resolveMediaType(newMimeType);
            values.put(FileColumns.MEDIA_TYPE, mediaType);
        }

        if ((!isHidden && wasHidden) || !isSameMimeType) {
            // Set the modifier as MODIFIER_FUSE so that apps can scan the file to update the
            // metadata. Otherwise, scan will skip scanning this file because rename() doesn't
            // change lastModifiedTime and scan assumes there is no change in the file.
            values.put(FileColumns._MODIFIER, FileColumns._MODIFIER_FUSE);
        }

        final boolean allowHidden = isCallingPackageAllowedHidden();
        if (!newMimeType.equalsIgnoreCase("null") &&
                matchUri(getContentUriForFile(path, newMimeType), allowHidden) == AUDIO_MEDIA) {
            computeAudioLocalizedValues(values);
            computeAudioKeyValues(values);
        }
        FileUtils.computeValuesFromData(values, isFuseThread());
        return values;
    }

    private ArrayList<String> getIncludedDefaultDirectories() {
        final ArrayList<String> includedDefaultDirs = new ArrayList<>();
        if (checkCallingPermissionVideo(/*forWrite*/ true, null)) {
            includedDefaultDirs.add(Environment.DIRECTORY_DCIM);
            includedDefaultDirs.add(Environment.DIRECTORY_PICTURES);
            includedDefaultDirs.add(Environment.DIRECTORY_MOVIES);
        } else if (checkCallingPermissionImages(/*forWrite*/ true, null)) {
            includedDefaultDirs.add(Environment.DIRECTORY_DCIM);
            includedDefaultDirs.add(Environment.DIRECTORY_PICTURES);
        }
        return includedDefaultDirs;
    }

    /**
     * Gets all files in the given {@code path} and subdirectories of the given {@code path}.
     */
    private ArrayList<String> getAllFilesForRenameDirectory(String oldPath) {
        final String selection = FileColumns.DATA + " LIKE ? ESCAPE '\\'"
                + " and mime_type not like 'null'";
        final String[] selectionArgs = new String[] {DatabaseUtils.escapeForLike(oldPath) + "/%"};
        ArrayList<String> fileList = new ArrayList<>();

        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try (final Cursor c = query(FileUtils.getContentUriForPath(oldPath),
                new String[] {MediaColumns.DATA}, selection, selectionArgs, null)) {
            while (c.moveToNext()) {
                String filePath = c.getString(0);
                filePath = filePath.replaceFirst(Pattern.quote(oldPath + "/"), "");
                fileList.add(filePath);
            }
        } finally {
            restoreLocalCallingIdentity(token);
        }
        return fileList;
    }

    /**
     * Gets files in the given {@code path} and subdirectories of the given {@code path} for which
     * calling package has write permissions.
     *
     * This method throws {@code IllegalArgumentException} if the directory has one or more
     * files for which calling package doesn't have write permission or if file type is not
     * supported in {@code newPath}
     */
    private ArrayList<String> getWritableFilesForRenameDirectory(String oldPath, String newPath)
            throws IllegalArgumentException {
        // Try a simple check to see if the caller has full access to the given collections first
        // before falling back to performing a query to probe for access.
        final String oldRelativePath = extractRelativePathWithDisplayName(oldPath);
        final String newRelativePath = extractRelativePathWithDisplayName(newPath);
        boolean hasFullAccessToOldPath = false;
        boolean hasFullAccessToNewPath = false;
        for (String defaultDir : getIncludedDefaultDirectories()) {
            if (oldRelativePath.startsWith(defaultDir)) hasFullAccessToOldPath = true;
            if (newRelativePath.startsWith(defaultDir)) hasFullAccessToNewPath = true;
        }
        if (hasFullAccessToNewPath && hasFullAccessToOldPath) {
            return getAllFilesForRenameDirectory(oldPath);
        }

        final int countAllFilesInDirectory;
        final String selection = FileColumns.DATA + " LIKE ? ESCAPE '\\'"
                + " and mime_type not like 'null'";
        final String[] selectionArgs = new String[] {DatabaseUtils.escapeForLike(oldPath) + "/%"};

        final Uri uriOldPath = FileUtils.getContentUriForPath(oldPath);

        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try (final Cursor c = query(uriOldPath, new String[] {MediaColumns._ID}, selection,
                selectionArgs, null)) {
            // get actual number of files in the given directory.
            countAllFilesInDirectory = c.getCount();
        } finally {
            restoreLocalCallingIdentity(token);
        }

        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_UPDATE,
                matchUri(uriOldPath, isCallingPackageAllowedHidden()), uriOldPath, Bundle.EMPTY,
                null);
        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(uriOldPath);
        } catch (VolumeNotFoundException e) {
            throw new IllegalStateException("Volume not found while querying files for renaming "
                    + oldPath);
        }

        ArrayList<String> fileList = new ArrayList<>();
        final String[] projection = {MediaColumns.DATA, MediaColumns.MIME_TYPE};
        try (Cursor c = qb.query(helper, projection, selection, selectionArgs, null, null, null,
                null, null)) {
            // Check if the calling package has write permission to all files in the given
            // directory. If calling package has write permission to all files in the directory, the
            // query with update uri should return same number of files as previous query.
            if (c.getCount() != countAllFilesInDirectory) {
                throw new IllegalArgumentException("Calling package doesn't have write permission "
                        + " to rename one or more files in " + oldPath);
            }
            while(c.moveToNext()) {
                String filePath = c.getString(0);
                filePath = filePath.replaceFirst(Pattern.quote(oldPath + "/"), "");

                final String mimeType = c.getString(1);
                if (!isMimeTypeSupportedInPath(newPath + "/" + filePath, mimeType)) {
                    throw new IllegalArgumentException("Can't rename " + oldPath + "/" + filePath
                            + ". Mime type " + mimeType + " not supported in " + newPath);
                }
                fileList.add(filePath);
            }
        }
        return fileList;
    }

    private int renameInLowerFs(String oldPath, String newPath) {
        try {
            Os.rename(oldPath, newPath);
            return 0;
        } catch (ErrnoException e) {
            final String errorMessage = "Rename " + oldPath + " to " + newPath + " failed.";
            Log.e(TAG, errorMessage, e);
            return e.errno;
        }
    }

    /**
     * Rename directory from {@code oldPath} to {@code newPath}.
     *
     * Renaming a directory is only allowed if calling package has write permission to all files in
     * the given directory tree and all file types in the given directory tree are supported by the
     * top level directory of new path. Renaming a directory is split into three steps:
     * 1. Check calling package's permissions for all files in the given directory tree. Also check
     *    file type support for all files in the {@code newPath}.
     * 2. Try updating database for all files in the directory.
     * 3. Rename the directory in lower file system. If rename in the lower file system is
     *    successful, commit database update.
     *
     * @param oldPath path of the directory to be renamed.
     * @param newPath new path of directory to be renamed.
     * @return 0 on successful rename, appropriate negated errno value if the rename is not allowed.
     * <ul>
     * <li>{@link OsConstants#EPERM} Renaming a directory with file types not supported by
     * {@code newPath} or renaming a directory with files for which calling package doesn't have
     * write permission.
     * This method can also return errno returned from {@code Os.rename} function.
     */
    private int renameDirectoryCheckedForFuse(String oldPath, String newPath) {
        final ArrayList<String> fileList;
        try {
            fileList = getWritableFilesForRenameDirectory(oldPath, newPath);
        } catch (IllegalArgumentException e) {
            final String errorMessage = "Rename " + oldPath + " to " + newPath + " failed. ";
            Log.e(TAG, errorMessage, e);
            return OsConstants.EPERM;
        }

        return renameDirectoryUncheckedForFuse(oldPath, newPath, fileList);
    }

    private int renameDirectoryUncheckedForFuse(String oldPath, String newPath,
            ArrayList<String> fileList) {
        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(FileUtils.getContentUriForPath(oldPath));
        } catch (VolumeNotFoundException e) {
            throw new IllegalStateException("Volume not found while trying to update database for "
                    + oldPath, e);
        }

        helper.beginTransaction();
        try {
            final Bundle qbExtras = new Bundle();
            qbExtras.putStringArrayList(INCLUDED_DEFAULT_DIRECTORIES,
                    getIncludedDefaultDirectories());
            final boolean wasHidden = FileUtils.shouldDirBeHidden(new File(oldPath));
            final boolean isHidden = FileUtils.shouldDirBeHidden(new File(newPath));
            for (String filePath : fileList) {
                final String newFilePath = newPath + "/" + filePath;
                final String mimeType = MimeUtils.resolveMimeType(new File(newFilePath));
                if(!updateDatabaseForFuseRename(helper, oldPath + "/" + filePath, newFilePath,
                        getContentValuesForFuseRename(newFilePath, mimeType, wasHidden, isHidden,
                                /* isSameMimeType */ true),
                        qbExtras)) {
                    Log.e(TAG, "Calling package doesn't have write permission to rename file.");
                    return OsConstants.EPERM;
                }
            }

            // Rename the directory in lower file system.
            int errno = renameInLowerFs(oldPath, newPath);
            if (errno == 0) {
                helper.setTransactionSuccessful();
            } else {
                return errno;
            }
        } finally {
            helper.endTransaction();
        }
        // Directory movement might have made new/old path hidden.
        scanRenamedDirectoryForFuse(oldPath, newPath);
        return 0;
    }

    /**
     * Rename a file from {@code oldPath} to {@code newPath}.
     *
     * Renaming a file is split into three parts:
     * 1. Check if {@code newPath} supports new file type.
     * 2. Try updating database entry from {@code oldPath} to {@code newPath}. This update may fail
     *    if calling package doesn't have write permission for {@code oldPath} and {@code newPath}.
     * 3. Rename the file in lower file system. If Rename in lower file system succeeds, commit
     *    database update.
     * @param oldPath path of the file to be renamed.
     * @param newPath new path of the file to be renamed.
     * @return 0 on successful rename, appropriate negated errno value if the rename is not allowed.
     * <ul>
     * <li>{@link OsConstants#EPERM} Calling package doesn't have write permission for
     * {@code oldPath} or {@code newPath}, or file type is not supported by {@code newPath}.
     * This method can also return errno returned from {@code Os.rename} function.
     */
    private int renameFileCheckedForFuse(String oldPath, String newPath) {
        // Check if new mime type is supported in new path.
        final String newMimeType = MimeUtils.resolveMimeType(new File(newPath));
        if (!isMimeTypeSupportedInPath(newPath, newMimeType)) {
            return OsConstants.EPERM;
        }
        return renameFileForFuse(oldPath, newPath, /* bypassRestrictions */ false) ;
    }

    private int renameFileUncheckedForFuse(String oldPath, String newPath) {
        return renameFileForFuse(oldPath, newPath, /* bypassRestrictions */ true) ;
    }

    private int renameFileForFuse(String oldPath, String newPath, boolean bypassRestrictions) {
        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(FileUtils.getContentUriForPath(oldPath));
        } catch (VolumeNotFoundException e) {
            throw new IllegalStateException("Failed to update database row with " + oldPath, e);
        }

        final boolean wasHidden = FileUtils.shouldFileBeHidden(new File(oldPath));
        final boolean isHidden = FileUtils.shouldFileBeHidden(new File(newPath));
        helper.beginTransaction();
        try {
            final String newMimeType = MimeUtils.resolveMimeType(new File(newPath));
            final String oldMimeType = MimeUtils.resolveMimeType(new File(oldPath));
            final boolean isSameMimeType = newMimeType.equalsIgnoreCase(oldMimeType);
            ContentValues contentValues = getContentValuesForFuseRename(newPath, newMimeType,
                    wasHidden, isHidden, isSameMimeType);
            if (!updateDatabaseForFuseRename(helper, oldPath, newPath, contentValues)) {
                if (!bypassRestrictions) {
                    // Check for other URI format grants for oldPath only. Check right before
                    // returning EPERM, to leave positive case performance unaffected.
                    if (!renameWithOtherUriGrants(helper, oldPath, newPath, contentValues)) {
                        Log.e(TAG, "Calling package doesn't have write permission to rename file.");
                        return OsConstants.EPERM;
                    }
                } else if (!maybeRemoveOwnerPackageForFuseRename(helper, newPath)) {
                    Log.wtf(TAG, "Couldn't clear owner package name for " + newPath);
                    return OsConstants.EPERM;
                }
            }

            // Try renaming oldPath to newPath in lower file system.
            int errno = renameInLowerFs(oldPath, newPath);
            if (errno == 0) {
                helper.setTransactionSuccessful();
            } else {
                return errno;
            }
        } finally {
            helper.endTransaction();
        }
        // The above code should have taken are of the mime/media type of the new file,
        // even if it was moved to/from a hidden directory.
        // This leaves cases where the source/dest of the move is a .nomedia file itself. Eg:
        // 1) /sdcard/foo/.nomedia => /sdcard/foo/bar.mp3
        //    in this case, the code above has given bar.mp3 the correct mime type, but we should
        //    still can /sdcard/foo, because it's now no longer hidden
        // 2) /sdcard/foo/.nomedia => /sdcard/bar/.nomedia
        //    in this case, we need to scan both /sdcard/foo and /sdcard/bar/
        // 3) /sdcard/foo/bar.mp3 => /sdcard/foo/.nomedia
        //    in this case, we need to scan all of /sdcard/foo
        if (extractDisplayName(oldPath).equals(".nomedia")) {
            scanFileAsMediaProvider(new File(oldPath).getParentFile(), REASON_DEMAND);
        }
        if (extractDisplayName(newPath).equals(".nomedia")) {
            scanFileAsMediaProvider(new File(newPath).getParentFile(), REASON_DEMAND);
        }

        return 0;
    }

    /**
     * Rename file by checking for other URI grants on oldPath
     *
     * We don't support replace scenario by checking for other URI grants on newPath (if it exists).
     */
    private boolean renameWithOtherUriGrants(DatabaseHelper helper, String oldPath, String newPath,
            ContentValues contentValues) {
        final Uri oldPathGrantedUri = getOtherUriGrantsForPath(oldPath, /* forWrite */ true);
        if (oldPathGrantedUri == null) {
            return false;
        }
        return updateDatabaseForFuseRename(helper, oldPath, newPath, contentValues, Bundle.EMPTY,
                oldPathGrantedUri);
    }

    /**
     * Rename file/directory without imposing any restrictions.
     *
     * We don't impose any rename restrictions for apps that bypass scoped storage restrictions.
     * However, we update database entries for renamed files to keep the database consistent.
     */
    private int renameUncheckedForFuse(String oldPath, String newPath) {
        if (new File(oldPath).isFile()) {
            return renameFileUncheckedForFuse(oldPath, newPath);
        } else {
            return renameDirectoryUncheckedForFuse(oldPath, newPath,
                    getAllFilesForRenameDirectory(oldPath));
        }
    }

    /**
     * Rename file or directory from {@code oldPath} to {@code newPath}.
     *
     * @param oldPath path of the file or directory to be renamed.
     * @param newPath new path of the file or directory to be renamed.
     * @param uid UID of the calling package.
     * @return 0 on successful rename, appropriate errno value if the rename is not allowed.
     * <ul>
     * <li>{@link OsConstants#ENOENT} Renaming a non-existing file or renaming a file from path that
     * is not indexed by MediaProvider database.
     * <li>{@link OsConstants#EPERM} Renaming a default directory or renaming a file to a file type
     * not supported by new path.
     * This method can also return errno returned from {@code Os.rename} function.
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public int renameForFuse(String oldPath, String newPath, int uid) {
        final String errorMessage = "Rename " + oldPath + " to " + newPath + " failed. ";
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), oldPath);

        try {
            if (isPrivatePackagePathNotAccessibleByCaller(oldPath)
                    || isPrivatePackagePathNotAccessibleByCaller(newPath)) {
                return OsConstants.EACCES;
            }

            if (!newPath.equals(getAbsoluteSanitizedPath(newPath))) {
                Log.e(TAG, "New path name contains invalid characters.");
                return OsConstants.EPERM;
            }

            if (shouldBypassDatabaseAndSetDirtyForFuse(uid, oldPath)
                    && shouldBypassDatabaseAndSetDirtyForFuse(uid, newPath)) {
                return renameInLowerFs(oldPath, newPath);
            }

            if (shouldBypassFuseRestrictions(/*forWrite*/ true, oldPath)
                    && shouldBypassFuseRestrictions(/*forWrite*/ true, newPath)) {
                return renameUncheckedForFuse(oldPath, newPath);
            }
            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (isCallingPackageRequestingLegacy()) {
                return OsConstants.EACCES;
            }

            final String[] oldRelativePath = sanitizePath(extractRelativePath(oldPath));
            final String[] newRelativePath = sanitizePath(extractRelativePath(newPath));
            if (oldRelativePath.length == 0 || newRelativePath.length == 0) {
                // Rename not allowed on paths that can't be translated to RELATIVE_PATH.
                Log.e(TAG, errorMessage +  "Invalid path.");
                return OsConstants.EPERM;
            }
            if (oldRelativePath.length == 1 && TextUtils.isEmpty(oldRelativePath[0])) {
                // Allow rename of files/folders other than default directories.
                final String displayName = extractDisplayName(oldPath);
                for (String defaultFolder : DEFAULT_FOLDER_NAMES) {
                    if (displayName.equals(defaultFolder)) {
                        Log.e(TAG, errorMessage + oldPath + " is a default folder."
                                + " Renaming a default folder is not allowed.");
                        return OsConstants.EPERM;
                    }
                }
            }
            if (newRelativePath.length == 1 && TextUtils.isEmpty(newRelativePath[0])) {
                Log.e(TAG, errorMessage +  newPath + " is in root folder."
                        + " Renaming a file/directory to root folder is not allowed");
                return OsConstants.EPERM;
            }

            // TODO(b/177049768): We shouldn't use getExternalStorageDirectory for these checks.
            final File directoryAndroid = new File(Environment.getExternalStorageDirectory(),
                    DIRECTORY_ANDROID_LOWER_CASE);
            final File directoryAndroidMedia = new File(directoryAndroid, DIRECTORY_MEDIA);
            if (directoryAndroidMedia.getAbsolutePath().equalsIgnoreCase(oldPath)) {
                // Don't allow renaming 'Android/media' directory.
                // Android/[data|obb] are bind mounted and these paths don't go through FUSE.
                Log.e(TAG, errorMessage +  oldPath + " is a default folder in app external "
                        + "directory. Renaming a default folder is not allowed.");
                return OsConstants.EPERM;
            } else if (FileUtils.contains(directoryAndroid, new File(newPath))) {
                if (newRelativePath.length == 1) {
                    // New path is Android/*. Path is directly under Android. Don't allow moving
                    // files and directories to Android/.
                    Log.e(TAG, errorMessage +  newPath + " is in app external directory. "
                            + "Renaming a file/directory to app external directory is not "
                            + "allowed.");
                    return OsConstants.EPERM;
                } else if(!FileUtils.contains(directoryAndroidMedia, new File(newPath))) {
                    // New path is  Android/*/*. Don't allow moving of files or directories
                    // to app external directory other than media directory.
                    Log.e(TAG, errorMessage +  newPath + " is not in external media directory."
                            + "File/directory can only be renamed to a path in external media "
                            + "directory. Renaming file/directory to path in other external "
                            + "directories is not allowed");
                    return OsConstants.EPERM;
                }
            }

            // Continue renaming files/directories if rename of oldPath to newPath is allowed.
            if (new File(oldPath).isFile()) {
                return renameFileCheckedForFuse(oldPath, newPath);
            } else {
                return renameDirectoryCheckedForFuse(oldPath, newPath);
            }
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    @Override
    public int checkUriPermission(@NonNull Uri uri, int uid,
            /* @Intent.AccessUriMode */ int modeFlags) {
        final LocalCallingIdentity token = clearLocalCallingIdentity(
                LocalCallingIdentity.fromExternal(getContext(), mUserCache, uid));

        if (isRedactedUri(uri)) {
            if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
                // we don't allow write grants on redacted uris.
                return PackageManager.PERMISSION_DENIED;
            }

            uri = getUriForRedactedUri(uri);
        }

        if (isPickerUri(uri)) {
            // Do not allow implicit access (by the virtue of ownership/permission) to picker uris.
            // Picker uris should have explicit permission grants.
            // If the calling app A has an explicit grant on picker uri, UriGrantsManagerService
            // will check the grant status and allow app A to grant the uri to app B (without
            // calling into MediaProvider)
            return PackageManager.PERMISSION_DENIED;
        }

        try {
            final boolean allowHidden = isCallingPackageAllowedHidden();
            final int table = matchUri(uri, allowHidden);

            final DatabaseHelper helper;
            try {
                helper = getDatabaseForUri(uri);
            } catch (VolumeNotFoundException e) {
                return PackageManager.PERMISSION_DENIED;
            }

            final int type;
            if ((modeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
                type = TYPE_UPDATE;
            } else {
                type = TYPE_QUERY;
            }

            final SQLiteQueryBuilder qb = getQueryBuilder(type, table, uri, Bundle.EMPTY, null);
            try (Cursor c = qb.query(helper,
                    new String[] { BaseColumns._ID }, null, null, null, null, null, null, null)) {
                if (c.getCount() == 1) {
                    c.moveToFirst();
                    final long cursorId = c.getLong(0);

                    long uriId = -1;
                    try {
                        uriId = ContentUris.parseId(uri);
                    } catch (NumberFormatException ignored) {
                        // if the id is not a number, the uri doesn't have a valid ID at the end of
                        // the uri, (i.e., uri is uri of the table not of the item/row)
                    }

                    if (uriId != -1 && cursorId == uriId) {
                        return PackageManager.PERMISSION_GRANTED;
                    }
                }
            }

            // For the uri with id cases, if it isn't returned in above query section, the result
            // isn't as expected. Don't grant the permission.
            switch (table) {
                case AUDIO_MEDIA_ID:
                case IMAGES_MEDIA_ID:
                case VIDEO_MEDIA_ID:
                case DOWNLOADS_ID:
                case FILES_ID:
                case AUDIO_MEDIA_ID_GENRES_ID:
                case AUDIO_GENRES_ID:
                case AUDIO_PLAYLISTS_ID:
                case AUDIO_PLAYLISTS_ID_MEMBERS_ID:
                case AUDIO_ARTISTS_ID:
                case AUDIO_ALBUMS_ID:
                    return PackageManager.PERMISSION_DENIED;
                default:
                    // continue below
            }

            // If the uri is a valid content uri and doesn't have a valid ID at the end of the uri,
            // (i.e., uri is uri of the table not of the item/row), and app doesn't request prefix
            // grant, we are willing to grant this uri permission since this doesn't grant them any
            // extra access. This grant will only grant permissions on given uri, it will not grant
            // access to db rows of the corresponding table.
            if ((modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) == 0) {
                return PackageManager.PERMISSION_GRANTED;
            }
        } finally {
            restoreLocalCallingIdentity(token);
        }
        return PackageManager.PERMISSION_DENIED;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        return query(uri, projection,
                DatabaseUtils.createSqlQueryBundle(selection, selectionArgs, sortOrder), null);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, Bundle queryArgs, CancellationSignal signal) {
        return query(uri, projection, queryArgs, signal, /* forSelf */ false);
    }

    private Cursor query(Uri uri, String[] projection, Bundle queryArgs,
            CancellationSignal signal, boolean forSelf) {
        Trace.beginSection("query");
        try {
            return queryInternal(uri, projection, queryArgs, signal, forSelf);
        } catch (FallbackException e) {
            return e.translateForQuery(getCallingPackageTargetSdkVersion());
        } finally {
            Trace.endSection();
        }
    }

    private Cursor queryInternal(Uri uri, String[] projection, Bundle queryArgs,
            CancellationSignal signal, boolean forSelf) throws FallbackException {
        if (isPickerUri(uri)) {
            return mPickerUriResolver.query(uri, projection, mCallingIdentity.get().pid,
                    mCallingIdentity.get().uid);
        }

        final String volumeName = getVolumeName(uri);
        PulledMetrics.logVolumeAccessViaMediaProvider(getCallingUidOrSelf(), volumeName);
        queryArgs = (queryArgs != null) ? queryArgs : new Bundle();

        // INCLUDED_DEFAULT_DIRECTORIES extra should only be set inside MediaProvider.
        queryArgs.remove(INCLUDED_DEFAULT_DIRECTORIES);

        final ArraySet<String> honoredArgs = new ArraySet<>();
        DatabaseUtils.resolveQueryArgs(queryArgs, honoredArgs::add, this::ensureCustomCollator);

        Uri redactedUri = null;
        // REDACTED_URI_BUNDLE_KEY extra should only be set inside MediaProvider.
        queryArgs.remove(QUERY_ARG_REDACTED_URI);
        if (isRedactedUri(uri)) {
            redactedUri = uri;
            uri = getUriForRedactedUri(uri);
            queryArgs.putParcelable(QUERY_ARG_REDACTED_URI, redactedUri);
        }

        uri = safeUncanonicalize(uri);

        final int targetSdkVersion = getCallingPackageTargetSdkVersion();
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int table = matchUri(uri, allowHidden);

        //Log.v(TAG, "query: uri="+uri+", selection="+selection);
        // handle MEDIA_SCANNER before calling getDatabaseForUri()
        if (table == MEDIA_SCANNER) {
            // create a cursor to return volume currently being scanned by the media scanner
            MatrixCursor c = new MatrixCursor(new String[] {MediaStore.MEDIA_SCANNER_VOLUME});
            c.addRow(new String[] {mMediaScannerVolume});
            return c;
        }

        // Used temporarily (until we have unique media IDs) to get an identifier
        // for the current sd card, so that the music app doesn't have to use the
        // non-public getFatVolumeId method
        if (table == FS_ID) {
            MatrixCursor c = new MatrixCursor(new String[] {"fsid"});
            c.addRow(new Integer[] {mVolumeId});
            return c;
        }

        if (table == VERSION) {
            MatrixCursor c = new MatrixCursor(new String[] {"version"});
            c.addRow(new Integer[] {DatabaseHelper.getDatabaseVersion(getContext())});
            return c;
        }

        // TODO(b/195008831): Add test to verify that apps can't access
        if (table == PICKER_INTERNAL_MEDIA) {
            return mPickerDataLayer.fetchMedia(queryArgs);
        } else if (table == PICKER_INTERNAL_ALBUMS) {
            return mPickerDataLayer.fetchAlbums(queryArgs);
        }

        final DatabaseHelper helper = getDatabaseForUri(uri);
        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_QUERY, table, uri, queryArgs,
                honoredArgs::add);

        if (targetSdkVersion < Build.VERSION_CODES.R) {
            // Some apps are abusing "ORDER BY" clauses to inject "LIMIT"
            // clauses; gracefully lift them out.
            DatabaseUtils.recoverAbusiveSortOrder(queryArgs);

            // Some apps are abusing the Uri query parameters to inject LIMIT
            // clauses; gracefully lift them out.
            DatabaseUtils.recoverAbusiveLimit(uri, queryArgs);
        }

        if (targetSdkVersion < Build.VERSION_CODES.Q) {
            // Some apps are abusing the "WHERE" clause by injecting "GROUP BY"
            // clauses; gracefully lift them out.
            DatabaseUtils.recoverAbusiveSelection(queryArgs);

            // Some apps are abusing the first column to inject "DISTINCT";
            // gracefully lift them out.
            if ((projection != null) && (projection.length > 0)
                    && projection[0].startsWith("DISTINCT ")) {
                projection[0] = projection[0].substring("DISTINCT ".length());
                qb.setDistinct(true);
            }

            // Some apps are generating thumbnails with getThumbnail(), but then
            // ignoring the returned Bitmap and querying the raw table; give
            // them a row with enough information to find the original image.
            final String selection = queryArgs.getString(QUERY_ARG_SQL_SELECTION);
            if ((table == IMAGES_THUMBNAILS || table == VIDEO_THUMBNAILS)
                    && !TextUtils.isEmpty(selection)) {
                final Matcher matcher = PATTERN_SELECTION_ID.matcher(selection);
                if (matcher.matches()) {
                    final long id = Long.parseLong(matcher.group(1));

                    final Uri fullUri;
                    if (table == IMAGES_THUMBNAILS) {
                        fullUri = ContentUris.withAppendedId(
                                Images.Media.getContentUri(volumeName), id);
                    } else if (table == VIDEO_THUMBNAILS) {
                        fullUri = ContentUris.withAppendedId(
                                Video.Media.getContentUri(volumeName), id);
                    } else {
                        throw new IllegalArgumentException();
                    }

                    final MatrixCursor cursor = new MatrixCursor(projection);
                    final File file = ContentResolver.encodeToFile(
                            fullUri.buildUpon().appendPath("thumbnail").build());
                    final String data = file.getAbsolutePath();
                    cursor.newRow().add(MediaColumns._ID, null)
                            .add(Images.Thumbnails.IMAGE_ID, id)
                            .add(Video.Thumbnails.VIDEO_ID, id)
                            .add(MediaColumns.DATA, data);
                    return cursor;
                }
            }
        }

        // Update locale if necessary.
        if (helper.isInternal() && !Locale.getDefault().equals(mLastLocale)) {
            Log.i(TAG, "Updating locale within queryInternal");
            onLocaleChanged(false);
        }

        final Cursor c = qb.query(helper, projection, queryArgs, signal);
        if (c != null && !forSelf) {
            // As a performance optimization, only configure notifications when
            // resulting cursor will leave our process
            final boolean callerIsRemote = mCallingIdentity.get().pid != android.os.Process.myPid();
            if (callerIsRemote && !isFuseThread()) {
                c.setNotificationUri(getContext().getContentResolver(), uri);
            }

            final Bundle extras = new Bundle();
            extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS,
                    honoredArgs.toArray(new String[honoredArgs.size()]));
            c.setExtras(extras);
        }

        // Query was on a redacted URI, update the sensitive information such as the _ID, DATA etc.
        if (redactedUri != null && c != null) {
            try {
                return getRedactedUriCursor(redactedUri, c);
            } finally {
                c.close();
            }
        }

        return c;
    }

    private boolean isUriSupportedForRedaction(Uri uri) {
        final int match = matchUri(uri, true);
        return REDACTED_URI_SUPPORTED_TYPES.contains(match);
    }

    private Cursor getRedactedUriCursor(Uri redactedUri, @NonNull Cursor c) {
        final HashSet<String> columnNames = new HashSet<>(Arrays.asList(c.getColumnNames()));
        final MatrixCursor redactedUriCursor = new MatrixCursor(c.getColumnNames());
        final String redactedUriId = redactedUri.getLastPathSegment();

        if (!c.moveToFirst()) {
            return redactedUriCursor;
        }

        // NOTE: It is safe to assume that there will only be one entry corresponding to a
        // redacted URI as it corresponds to a unique DB entry.
        if (c.getCount() != 1) {
            throw new AssertionError("Two rows corresponding to " + redactedUri.toString()
                    + " found, when only one expected");
        }

        final MatrixCursor.RowBuilder row = redactedUriCursor.newRow();
        for (String columnName : c.getColumnNames()) {
            final int colIndex = c.getColumnIndex(columnName);
            if (c.getType(colIndex) == FIELD_TYPE_BLOB) {
                row.add(c.getBlob(colIndex));
            } else {
                row.add(c.getString(colIndex));
            }
        }

        String ext = getFileExtensionFromCursor(c, columnNames);
        ext = ext == null ? "" : "." + ext;
        final String displayName = redactedUriId + ext;
        final String data = buildPrimaryVolumeFile(uidToUserId(Binder.getCallingUid()),
                getRedactedRelativePath(), displayName).getAbsolutePath();

        updateRow(columnNames, MediaColumns._ID, row, redactedUriId);
        updateRow(columnNames, MediaColumns.DISPLAY_NAME, row, displayName);
        updateRow(columnNames, MediaColumns.RELATIVE_PATH, row, getRedactedRelativePath());
        updateRow(columnNames, MediaColumns.BUCKET_DISPLAY_NAME, row, getRedactedRelativePath());
        updateRow(columnNames, MediaColumns.DATA, row, data);
        updateRow(columnNames, MediaColumns.DOCUMENT_ID, row, null);
        updateRow(columnNames, MediaColumns.INSTANCE_ID, row, null);
        updateRow(columnNames, MediaColumns.BUCKET_ID, row, null);

        return redactedUriCursor;
    }

    @Nullable
    private static String getFileExtensionFromCursor(@NonNull Cursor c,
            @NonNull HashSet<String> columnNames) {
        if (columnNames.contains(MediaColumns.DATA)) {
            return extractFileExtension(c.getString(c.getColumnIndex(MediaColumns.DATA)));
        }
        if (columnNames.contains(MediaColumns.DISPLAY_NAME)) {
            return extractFileExtension(c.getString(c.getColumnIndex(MediaColumns.DISPLAY_NAME)));
        }
        return null;
    }

    private void updateRow(HashSet<String> columnNames, String columnName,
            MatrixCursor.RowBuilder row, Object val) {
        if (columnNames.contains(columnName)) {
            row.add(columnName, val);
        }
    }

    private Uri getUriForRedactedUri(Uri redactedUri) {
        final Uri.Builder builder = redactedUri.buildUpon();
        builder.path(null);
        final List<String> segments = redactedUri.getPathSegments();
        for (int i = 0; i < segments.size() - 1; i++) {
            builder.appendPath(segments.get(i));
        }

        DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(redactedUri);
        } catch (VolumeNotFoundException e) {
            throw e.rethrowAsIllegalArgumentException();
        }

        try (final Cursor c = helper.runWithoutTransaction(
                (db) -> db.query("files", new String[]{MediaColumns._ID},
                        FileColumns.REDACTED_URI_ID + "=?",
                        new String[]{redactedUri.getLastPathSegment()}, null, null, null))) {
            if (!c.moveToFirst()) {
                throw new IllegalArgumentException(
                        "Uri: " + redactedUri.toString() + " not found.");
            }

            builder.appendPath(c.getString(0));
            return builder.build();
        }
    }

    private boolean isRedactedUri(Uri uri) {
        String id = uri.getLastPathSegment();
        return id != null && id.startsWith(REDACTED_URI_ID_PREFIX)
                && id.length() == REDACTED_URI_ID_SIZE;
    }

    @Override
    public String getType(Uri url) {
        final int match = matchUri(url, true);
        switch (match) {
            case IMAGES_MEDIA_ID:
            case AUDIO_MEDIA_ID:
            case AUDIO_PLAYLISTS_ID:
            case AUDIO_PLAYLISTS_ID_MEMBERS_ID:
            case VIDEO_MEDIA_ID:
            case DOWNLOADS_ID:
            case FILES_ID:
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                try (Cursor cursor = queryForSingleItem(url,
                        new String[] { MediaColumns.MIME_TYPE }, null, null, null)) {
                    return cursor.getString(0);
                } catch (FileNotFoundException e) {
                    throw new IllegalArgumentException(e.getMessage());
                } finally {
                     restoreLocalCallingIdentity(token);
                }

            case IMAGES_MEDIA:
            case IMAGES_THUMBNAILS:
                return Images.Media.CONTENT_TYPE;

            case AUDIO_ALBUMART_ID:
            case AUDIO_ALBUMART_FILE_ID:
            case IMAGES_THUMBNAILS_ID:
            case VIDEO_THUMBNAILS_ID:
                return "image/jpeg";

            case AUDIO_MEDIA:
            case AUDIO_GENRES_ID_MEMBERS:
            case AUDIO_PLAYLISTS_ID_MEMBERS:
                return Audio.Media.CONTENT_TYPE;

            case AUDIO_GENRES:
            case AUDIO_MEDIA_ID_GENRES:
                return Audio.Genres.CONTENT_TYPE;
            case AUDIO_GENRES_ID:
            case AUDIO_MEDIA_ID_GENRES_ID:
                return Audio.Genres.ENTRY_CONTENT_TYPE;
            case AUDIO_PLAYLISTS:
                return Audio.Playlists.CONTENT_TYPE;

            case VIDEO_MEDIA:
                return Video.Media.CONTENT_TYPE;
            case DOWNLOADS:
                return Downloads.CONTENT_TYPE;

            case PICKER_ID:
                return mPickerUriResolver.getType(url);
        }
        throw new IllegalStateException("Unknown URL : " + url);
    }

    @VisibleForTesting
    void ensureFileColumns(@NonNull Uri uri, @NonNull ContentValues values)
            throws VolumeArgumentException, VolumeNotFoundException {
        final LocalUriMatcher matcher = new LocalUriMatcher(MediaStore.AUTHORITY);
        final int match = matcher.matchUri(uri, true);
        ensureNonUniqueFileColumns(match, uri, Bundle.EMPTY, values, null /* currentPath */);
    }

    private void ensureUniqueFileColumns(int match, @NonNull Uri uri, @NonNull Bundle extras,
            @NonNull ContentValues values, @Nullable String currentPath)
            throws VolumeArgumentException, VolumeNotFoundException {
        ensureFileColumns(match, uri, extras, values, true, currentPath);
    }

    private void ensureNonUniqueFileColumns(int match, @NonNull Uri uri,
            @NonNull Bundle extras, @NonNull ContentValues values, @Nullable String currentPath)
            throws VolumeArgumentException, VolumeNotFoundException {
        ensureFileColumns(match, uri, extras, values, false, currentPath);
    }

    /**
     * Get the various file-related {@link MediaColumns} in the given
     * {@link ContentValues} into a consistent condition. Also validates that defined
     * columns are valid for the given {@link Uri}, such as ensuring that only
     * {@code image/*} can be inserted into
     * {@link android.provider.MediaStore.Images}.
     */
    private void ensureFileColumns(int match, @NonNull Uri uri, @NonNull Bundle extras,
            @NonNull ContentValues values, boolean makeUnique, @Nullable String currentPath)
            throws VolumeArgumentException, VolumeNotFoundException {
        Trace.beginSection("ensureFileColumns");

        Objects.requireNonNull(uri);
        Objects.requireNonNull(extras);
        Objects.requireNonNull(values);

        // Figure out defaults based on Uri being modified
        String defaultMimeType = ClipDescription.MIMETYPE_UNKNOWN;
        int defaultMediaType = FileColumns.MEDIA_TYPE_NONE;
        String defaultPrimary = Environment.DIRECTORY_DOWNLOADS;
        String defaultSecondary = null;
        List<String> allowedPrimary = Arrays.asList(
                Environment.DIRECTORY_DOWNLOADS,
                Environment.DIRECTORY_DOCUMENTS);
        switch (match) {
            case AUDIO_MEDIA:
            case AUDIO_MEDIA_ID:
                defaultMimeType = "audio/mpeg";
                defaultMediaType = FileColumns.MEDIA_TYPE_AUDIO;
                defaultPrimary = Environment.DIRECTORY_MUSIC;
                if (SdkLevel.isAtLeastS()) {
                    allowedPrimary = Arrays.asList(
                            Environment.DIRECTORY_ALARMS,
                            Environment.DIRECTORY_AUDIOBOOKS,
                            Environment.DIRECTORY_MUSIC,
                            Environment.DIRECTORY_NOTIFICATIONS,
                            Environment.DIRECTORY_PODCASTS,
                            Environment.DIRECTORY_RECORDINGS,
                            Environment.DIRECTORY_RINGTONES);
                } else {
                    allowedPrimary = Arrays.asList(
                            Environment.DIRECTORY_ALARMS,
                            Environment.DIRECTORY_AUDIOBOOKS,
                            Environment.DIRECTORY_MUSIC,
                            Environment.DIRECTORY_NOTIFICATIONS,
                            Environment.DIRECTORY_PODCASTS,
                            FileUtils.DIRECTORY_RECORDINGS,
                            Environment.DIRECTORY_RINGTONES);
                }
                break;
            case VIDEO_MEDIA:
            case VIDEO_MEDIA_ID:
                defaultMimeType = "video/mp4";
                defaultMediaType = FileColumns.MEDIA_TYPE_VIDEO;
                defaultPrimary = Environment.DIRECTORY_MOVIES;
                allowedPrimary = Arrays.asList(
                        Environment.DIRECTORY_DCIM,
                        Environment.DIRECTORY_MOVIES,
                        Environment.DIRECTORY_PICTURES);
                break;
            case IMAGES_MEDIA:
            case IMAGES_MEDIA_ID:
                defaultMimeType = "image/jpeg";
                defaultMediaType = FileColumns.MEDIA_TYPE_IMAGE;
                defaultPrimary = Environment.DIRECTORY_PICTURES;
                allowedPrimary = Arrays.asList(
                        Environment.DIRECTORY_DCIM,
                        Environment.DIRECTORY_PICTURES);
                break;
            case AUDIO_ALBUMART:
            case AUDIO_ALBUMART_ID:
                defaultMimeType = "image/jpeg";
                defaultMediaType = FileColumns.MEDIA_TYPE_IMAGE;
                defaultPrimary = Environment.DIRECTORY_MUSIC;
                allowedPrimary = Arrays.asList(defaultPrimary);
                defaultSecondary = DIRECTORY_THUMBNAILS;
                break;
            case VIDEO_THUMBNAILS:
            case VIDEO_THUMBNAILS_ID:
                defaultMimeType = "image/jpeg";
                defaultMediaType = FileColumns.MEDIA_TYPE_IMAGE;
                defaultPrimary = Environment.DIRECTORY_MOVIES;
                allowedPrimary = Arrays.asList(defaultPrimary);
                defaultSecondary = DIRECTORY_THUMBNAILS;
                break;
            case IMAGES_THUMBNAILS:
            case IMAGES_THUMBNAILS_ID:
                defaultMimeType = "image/jpeg";
                defaultMediaType = FileColumns.MEDIA_TYPE_IMAGE;
                defaultPrimary = Environment.DIRECTORY_PICTURES;
                allowedPrimary = Arrays.asList(defaultPrimary);
                defaultSecondary = DIRECTORY_THUMBNAILS;
                break;
            case AUDIO_PLAYLISTS:
            case AUDIO_PLAYLISTS_ID:
                defaultMimeType = "audio/mpegurl";
                defaultMediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
                defaultPrimary = Environment.DIRECTORY_MUSIC;
                allowedPrimary = Arrays.asList(
                        Environment.DIRECTORY_MUSIC,
                        Environment.DIRECTORY_MOVIES);
                break;
            case DOWNLOADS:
            case DOWNLOADS_ID:
                defaultPrimary = Environment.DIRECTORY_DOWNLOADS;
                allowedPrimary = Arrays.asList(defaultPrimary);
                break;
            case FILES:
            case FILES_ID:
                // Use defaults above
                break;
            default:
                Log.w(TAG, "Unhandled location " + uri + "; assuming generic files");
                break;
        }

        final String resolvedVolumeName = resolveVolumeName(uri);

        if (TextUtils.isEmpty(values.getAsString(MediaColumns.DATA))
                && MediaStore.VOLUME_INTERNAL.equals(resolvedVolumeName)) {
            // TODO: promote this to top-level check
            throw new UnsupportedOperationException(
                    "Writing to internal storage is not supported.");
        }

        // Force values when raw path provided
        if (!TextUtils.isEmpty(values.getAsString(MediaColumns.DATA))) {
            FileUtils.computeValuesFromData(values, isFuseThread());
        }

        final boolean isTargetSdkROrHigher =
                getCallingPackageTargetSdkVersion() >= Build.VERSION_CODES.R;
        final String displayName = values.getAsString(MediaColumns.DISPLAY_NAME);
        final String mimeTypeFromExt = TextUtils.isEmpty(displayName) ? null :
                MimeUtils.resolveMimeType(new File(displayName));

        if (TextUtils.isEmpty(values.getAsString(MediaColumns.MIME_TYPE))) {
            if (isTargetSdkROrHigher) {
                // Extract the MIME type from the display name if we couldn't resolve it from the
                // raw path
                if (mimeTypeFromExt != null) {
                    values.put(MediaColumns.MIME_TYPE, mimeTypeFromExt);
                } else {
                    // We couldn't resolve mimeType, it means that both display name and MIME type
                    // were missing in values, so we use defaultMimeType.
                    values.put(MediaColumns.MIME_TYPE, defaultMimeType);
                }
            } else if (defaultMediaType == FileColumns.MEDIA_TYPE_NONE) {
                values.put(MediaColumns.MIME_TYPE, mimeTypeFromExt);
            } else {
                // We don't use mimeTypeFromExt to preserve legacy behavior.
                values.put(MediaColumns.MIME_TYPE, defaultMimeType);
            }
        }

        String mimeType = values.getAsString(MediaColumns.MIME_TYPE);
        if (defaultMediaType == FileColumns.MEDIA_TYPE_NONE) {
            // We allow any mimeType for generic uri with default media type as MEDIA_TYPE_NONE.
        } else if (mimeType != null &&
                MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) == null) {
            if (mimeTypeFromExt != null &&
                    defaultMediaType == MimeUtils.resolveMediaType(mimeTypeFromExt)) {
                // If mimeType from extension matches the defaultMediaType of uri, we use mimeType
                // from file extension as mimeType. This is an effort to guess the mimeType when we
                // get unsupported mimeType.
                // Note: We can't force defaultMimeType because when we force defaultMimeType, we
                // will force the file extension as well. For example, if DISPLAY_NAME=Foo.png and
                // mimeType="image/*". If we force mimeType to be "image/jpeg", we append the file
                // name with the new file extension i.e., "Foo.png.jpg" where as the expected file
                // name was "Foo.png"
                values.put(MediaColumns.MIME_TYPE, mimeTypeFromExt);
            } else if (isTargetSdkROrHigher) {
                // We are here because given mimeType is unsupported also we couldn't guess valid
                // mimeType from file extension.
                throw new IllegalArgumentException("Unsupported MIME type " + mimeType);
            } else {
                // We can't throw error for legacy apps, so we try to use defaultMimeType.
                values.put(MediaColumns.MIME_TYPE, defaultMimeType);
            }
        }

        // Give ourselves reasonable defaults when missing
        if (TextUtils.isEmpty(values.getAsString(MediaColumns.DISPLAY_NAME))) {
            values.put(MediaColumns.DISPLAY_NAME,
                    String.valueOf(System.currentTimeMillis()));
        }
        final Integer formatObject = values.getAsInteger(FileColumns.FORMAT);
        final int format = formatObject == null ? 0 : formatObject.intValue();
        if (format == MtpConstants.FORMAT_ASSOCIATION) {
            values.putNull(MediaColumns.MIME_TYPE);
        }

        mimeType = values.getAsString(MediaColumns.MIME_TYPE);
        // Quick check MIME type against table
        if (mimeType != null) {
            PulledMetrics.logMimeTypeAccess(getCallingUidOrSelf(), mimeType);
            final int actualMediaType = MimeUtils.resolveMediaType(mimeType);
            if (defaultMediaType == FileColumns.MEDIA_TYPE_NONE) {
                // Give callers an opportunity to work with playlists and
                // subtitles using the generic files table
                switch (actualMediaType) {
                    case FileColumns.MEDIA_TYPE_PLAYLIST:
                        defaultMimeType = "audio/mpegurl";
                        defaultMediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
                        defaultPrimary = Environment.DIRECTORY_MUSIC;
                        allowedPrimary = new ArrayList<>(allowedPrimary);
                        allowedPrimary.add(Environment.DIRECTORY_MUSIC);
                        allowedPrimary.add(Environment.DIRECTORY_MOVIES);
                        break;
                    case FileColumns.MEDIA_TYPE_SUBTITLE:
                        defaultMimeType = "application/x-subrip";
                        defaultMediaType = FileColumns.MEDIA_TYPE_SUBTITLE;
                        defaultPrimary = Environment.DIRECTORY_MOVIES;
                        allowedPrimary = new ArrayList<>(allowedPrimary);
                        allowedPrimary.add(Environment.DIRECTORY_MUSIC);
                        allowedPrimary.add(Environment.DIRECTORY_MOVIES);
                        break;
                }
            } else if (defaultMediaType != actualMediaType) {
                final String[] split = defaultMimeType.split("/");
                throw new IllegalArgumentException(
                        "MIME type " + mimeType + " cannot be inserted into " + uri
                                + "; expected MIME type under " + split[0] + "/*");
            }
        }

        // Use default directories when missing
        if (TextUtils.isEmpty(values.getAsString(MediaColumns.RELATIVE_PATH))) {
            if (defaultSecondary != null) {
                values.put(MediaColumns.RELATIVE_PATH,
                        defaultPrimary + '/' + defaultSecondary + '/');
            } else {
                values.put(MediaColumns.RELATIVE_PATH,
                        defaultPrimary + '/');
            }
        }

        // Generate path when undefined
        if (TextUtils.isEmpty(values.getAsString(MediaColumns.DATA))) {
            // Note that just the volume name isn't enough to determine the path,
            // since we can manage different volumes with the same name for
            // different users. Instead, if we have a current path (which implies
            // an already existing file to be renamed), use that to derive the
            // user-id of the file, and in turn use that to derive the correct
            // volume. Cross-user renames are not supported without a specified
            // DATA column.
            File volumePath;
            UserHandle userHandle = mCallingIdentity.get().getUser();
            if (currentPath != null) {
                int userId = FileUtils.extractUserId(currentPath);
                if (userId != -1) {
                    userHandle = UserHandle.of(userId);
                }
            }
            try {
                volumePath = mVolumeCache.getVolumePath(resolvedVolumeName, userHandle);
            } catch (FileNotFoundException e) {
                throw new IllegalArgumentException(e);
            }

            FileUtils.sanitizeValues(values, /*rewriteHiddenFileName*/ !isFuseThread());
            FileUtils.computeDataFromValues(values, volumePath, isFuseThread());

            // Create result file
            File res = new File(values.getAsString(MediaColumns.DATA));
            try {
                if (makeUnique) {
                    res = FileUtils.buildUniqueFile(res.getParentFile(),
                            mimeType, res.getName());
                } else {
                    res = FileUtils.buildNonUniqueFile(res.getParentFile(),
                            mimeType, res.getName());
                }
            } catch (FileNotFoundException e) {
                throw new IllegalStateException(
                        "Failed to build unique file: " + res + " " + values);
            }

            // Require that content lives under well-defined directories to help
            // keep the user's content organized

            // Start by saying unchanged directories are valid
            final String currentDir = (currentPath != null)
                    ? new File(currentPath).getParent() : null;
            boolean validPath = res.getParent().equals(currentDir);

            // Next, consider allowing based on allowed primary directory
            final String[] relativePath = values.getAsString(MediaColumns.RELATIVE_PATH).split("/");
            final String primary = extractTopLevelDir(relativePath);
            if (!validPath) {
                validPath = containsIgnoreCase(allowedPrimary, primary);
            }

            // Next, consider allowing paths when referencing a related item
            final Uri relatedUri = extras.getParcelable(QUERY_ARG_RELATED_URI);
            if (!validPath && relatedUri != null) {
                try (Cursor c = queryForSingleItem(relatedUri, new String[] {
                        MediaColumns.MIME_TYPE,
                        MediaColumns.RELATIVE_PATH,
                }, null, null, null)) {
                    // If top-level MIME type matches, and relative path
                    // matches, then allow caller to place things here

                    final String expectedType = MimeUtils.extractPrimaryType(
                            c.getString(0));
                    final String actualType = MimeUtils.extractPrimaryType(
                            values.getAsString(MediaColumns.MIME_TYPE));
                    if (!Objects.equals(expectedType, actualType)) {
                        throw new IllegalArgumentException("Placement of " + actualType
                                + " item not allowed in relation to " + expectedType + " item");
                    }

                    final String expectedPath = c.getString(1);
                    final String actualPath = values.getAsString(MediaColumns.RELATIVE_PATH);
                    if (!Objects.equals(expectedPath, actualPath)) {
                        throw new IllegalArgumentException("Placement of " + actualPath
                                + " item not allowed in relation to " + expectedPath + " item");
                    }

                    // If we didn't see any trouble above, then we'll allow it
                    validPath = true;
                } catch (FileNotFoundException e) {
                    Log.w(TAG, "Failed to find related item " + relatedUri + ": " + e);
                }
            }

            // Consider allowing external media directory of calling package
            if (!validPath) {
                final String pathOwnerPackage = extractPathOwnerPackageName(res.getAbsolutePath());
                if (pathOwnerPackage != null) {
                    validPath = isExternalMediaDirectory(res.getAbsolutePath()) &&
                            isCallingIdentitySharedPackageName(pathOwnerPackage);
                }
            }

            // Allow apps with MANAGE_EXTERNAL_STORAGE to create files anywhere
            if (!validPath) {
                validPath = isCallingPackageManager();
            }

            // Allow system gallery to create image/video files.
            if (!validPath) {
                // System gallery can create image/video files in any existing directory, it can
                // also create subdirectories in any existing top-level directory. However, system
                // gallery is not allowed to create non-default top level directory.
                final boolean createNonDefaultTopLevelDir = primary != null &&
                        !FileUtils.buildPath(volumePath, primary).exists();
                validPath = !createNonDefaultTopLevelDir && canAccessMediaFile(
                        res.getAbsolutePath(), /*excludeNonSystemGallery*/ true);
            }

            // Nothing left to check; caller can't use this path
            if (!validPath) {
                throw new IllegalArgumentException(
                        "Primary directory " + primary + " not allowed for " + uri
                                + "; allowed directories are " + allowedPrimary);
            }

            boolean isFuseThread = isFuseThread();
            // Check if the following are true:
            // 1. Not a FUSE thread
            // 2. |res| is a child of a default dir and the default dir is missing
            // If true, we want to update the mTime of the volume root, after creating the dir
            // on the lower filesystem. This fixes some FileManagers relying on the mTime change
            // for UI updates
            File defaultDirVolumePath =
                    isFuseThread ? null : checkDefaultDirMissing(resolvedVolumeName, res);
            // Ensure all parent folders of result file exist
            res.getParentFile().mkdirs();
            if (!res.getParentFile().exists()) {
                throw new IllegalStateException("Failed to create directory: " + res);
            }
            touchFusePath(defaultDirVolumePath);

            values.put(MediaColumns.DATA, res.getAbsolutePath());
            // buildFile may have changed the file name, compute values to extract new DISPLAY_NAME.
            // Note: We can't extract displayName from res.getPath() because for pending & trashed
            // files DISPLAY_NAME will not be same as file name.
            FileUtils.computeValuesFromData(values, isFuseThread);
        } else {
            assertFileColumnsConsistent(match, uri, values);
        }

        assertPrivatePathNotInValues(values);

        // Drop columns that aren't relevant for special tables
        switch (match) {
            case AUDIO_ALBUMART:
            case VIDEO_THUMBNAILS:
            case IMAGES_THUMBNAILS:
                final Set<String> valid = getProjectionMap(MediaStore.Images.Thumbnails.class)
                        .keySet();
                for (String key : new ArraySet<>(values.keySet())) {
                    if (!valid.contains(key)) {
                        values.remove(key);
                    }
                }
                break;
        }

        Trace.endSection();
    }

    /**
     * For apps targetSdk >= S: Check that values does not contain any external private path.
     * For all apps: Check that values does not contain any other app's external private paths.
     */
    private void assertPrivatePathNotInValues(ContentValues values)
            throws IllegalArgumentException {
        ArrayList<String> relativePaths = new ArrayList<String>();
        relativePaths.add(extractRelativePath(values.getAsString(MediaColumns.DATA)));
        relativePaths.add(values.getAsString(MediaColumns.RELATIVE_PATH));

        for (final String relativePath : relativePaths) {
            if (!isDataOrObbRelativePath(relativePath)) {
                continue;
            }

            /**
             * Don't allow apps to insert/update database row to files in Android/data or
             * Android/obb dirs. These are app private directories and files in these private
             * directories can't be added to public media collection.
             *
             * Note: For backwards compatibility we allow apps with targetSdk < S to insert private
             * files to MediaProvider
             */
            if (CompatChanges.isChangeEnabled(ENABLE_CHECKS_FOR_PRIVATE_FILES,
                    Binder.getCallingUid())) {
                throw new IllegalArgumentException(
                        "Inserting private file: " + relativePath + " is not allowed.");
            }

            /**
             * Restrict all (legacy and non-legacy) apps from inserting paths in other
             * app's private directories.
             * Allow legacy apps to insert/update files in app private directories for backward
             * compatibility but don't allow them to do so in other app's private directories.
             */
            if (!isCallingIdentityAllowedAccessToDataOrObbPath(relativePath)) {
                throw new IllegalArgumentException(
                        "Inserting private file: " + relativePath + " is not allowed.");
            }
        }
    }

    /**
     * @return the default dir if {@code file} is a child of default dir and it's missing,
     * {@code null} otherwise.
     */
    private File checkDefaultDirMissing(String volumeName, File file) {
        String topLevelDir = FileUtils.extractTopLevelDir(file.getPath());
        if (topLevelDir != null && FileUtils.isDefaultDirectoryName(topLevelDir)) {
            try {
                File volumePath = getVolumePath(volumeName);
                if (!new File(volumePath, topLevelDir).exists()) {
                    return volumePath;
                }
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Failed to checkDefaultDirMissing for " + file, e);
            }
        }
        return null;
    }

    /** Updates mTime of {@code path} on the FUSE filesystem */
    private void touchFusePath(@Nullable File path) {
        if (path != null) {
            // Touch root of volume to update mTime on FUSE filesystem
            // This allows FileManagers that may be relying on mTime changes to update their UI
            File fusePath = toFuseFile(path);
            if (fusePath != null) {
                Log.i(TAG, "Touching FUSE path " + fusePath);
                fusePath.setLastModified(System.currentTimeMillis());
            }
        }
    }

    /**
     * Check that any requested {@link MediaColumns#DATA} paths actually
     * live on the storage volume being targeted.
     */
    private void assertFileColumnsConsistent(int match, Uri uri, ContentValues values)
            throws VolumeArgumentException, VolumeNotFoundException {
        if (!values.containsKey(MediaColumns.DATA)) return;

        final String volumeName = resolveVolumeName(uri);
        try {
            // Quick check that the requested path actually lives on volume
            final Collection<File> allowed = getAllowedVolumePaths(volumeName);
            final File actual = new File(values.getAsString(MediaColumns.DATA))
                    .getCanonicalFile();
            if (!FileUtils.contains(allowed, actual)) {
                throw new VolumeArgumentException(actual, allowed);
            }
        } catch (IOException e) {
            throw new VolumeNotFoundException(volumeName);
        }
    }

    @Override
    public int bulkInsert(Uri uri, ContentValues[] values) {
        final int targetSdkVersion = getCallingPackageTargetSdkVersion();
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        if (match == VOLUMES) {
            return super.bulkInsert(uri, values);
        }

        if (match == AUDIO_PLAYLISTS_ID || match == AUDIO_PLAYLISTS_ID_MEMBERS) {
            final String resolvedVolumeName = resolveVolumeName(uri);

            final long playlistId = Long.parseLong(uri.getPathSegments().get(3));
            final Uri playlistUri = ContentUris.withAppendedId(
                    MediaStore.Audio.Playlists.getContentUri(resolvedVolumeName), playlistId);

            final String audioVolumeName =
                    MediaStore.VOLUME_INTERNAL.equals(resolvedVolumeName)
                            ? MediaStore.VOLUME_INTERNAL : MediaStore.VOLUME_EXTERNAL;

            // Require that caller has write access to underlying media
            enforceCallingPermission(playlistUri, Bundle.EMPTY, true);
            for (ContentValues each : values) {
                final long audioId = each.getAsLong(Audio.Playlists.Members.AUDIO_ID);
                final Uri audioUri = Audio.Media.getContentUri(audioVolumeName, audioId);
                enforceCallingPermission(audioUri, Bundle.EMPTY, false);
            }

            return bulkInsertPlaylist(playlistUri, values);
        }

        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(uri);
        } catch (VolumeNotFoundException e) {
            return e.translateForUpdateDelete(targetSdkVersion);
        }

        helper.beginTransaction();
        try {
            final int result = super.bulkInsert(uri, values);
            helper.setTransactionSuccessful();
            return result;
        } finally {
            helper.endTransaction();
        }
    }

    private int bulkInsertPlaylist(@NonNull Uri uri, @NonNull ContentValues[] values) {
        Trace.beginSection("bulkInsertPlaylist");
        try {
            try {
                return addPlaylistMembers(uri, values);
            } catch (SQLiteConstraintException e) {
                if (getCallingPackageTargetSdkVersion() >= Build.VERSION_CODES.R) {
                    throw e;
                } else {
                    return 0;
                }
            }
        } catch (FallbackException e) {
            return e.translateForBulkInsert(getCallingPackageTargetSdkVersion());
        } finally {
            Trace.endSection();
        }
    }

    private long insertDirectory(@NonNull SQLiteDatabase db, @NonNull String path) {
        if (LOGV) Log.v(TAG, "inserting directory " + path);
        ContentValues values = new ContentValues();
        values.put(FileColumns.FORMAT, MtpConstants.FORMAT_ASSOCIATION);
        values.put(FileColumns.DATA, path);
        values.put(FileColumns.PARENT, getParent(db, path));
        values.put(FileColumns.OWNER_PACKAGE_NAME, extractPathOwnerPackageName(path));
        values.put(FileColumns.VOLUME_NAME, extractVolumeName(path));
        values.put(FileColumns.RELATIVE_PATH, extractRelativePath(path));
        values.put(FileColumns.DISPLAY_NAME, extractDisplayName(path));
        values.put(FileColumns.IS_DOWNLOAD, isDownload(path) ? 1 : 0);
        File file = new File(path);
        if (file.exists()) {
            values.put(FileColumns.DATE_MODIFIED, file.lastModified() / 1000);
        }
        return db.insert("files", FileColumns.DATE_MODIFIED, values);
    }

    private long getParent(@NonNull SQLiteDatabase db, @NonNull String path) {
        final String parentPath = new File(path).getParent();
        if (Objects.equals("/", parentPath)) {
            return -1;
        } else {
            synchronized (mDirectoryCache) {
                Long id = mDirectoryCache.get(parentPath);
                if (id != null) {
                    return id;
                }
            }

            final long id;
            try (Cursor c = db.query("files", new String[] { FileColumns._ID },
                    FileColumns.DATA + "=?", new String[] { parentPath }, null, null, null)) {
                if (c.moveToFirst()) {
                    id = c.getLong(0);
                } else {
                    id = insertDirectory(db, parentPath);
                }
            }

            synchronized (mDirectoryCache) {
                mDirectoryCache.put(parentPath, id);
            }
            return id;
        }
    }

    /**
     * @param c the Cursor whose title to retrieve
     * @return the result of {@link #getDefaultTitle(String)} if the result is valid; otherwise
     * the value of the {@code MediaStore.Audio.Media.TITLE} column
     */
    private String getDefaultTitleFromCursor(Cursor c) {
        String title = null;
        final int columnIndex = c.getColumnIndex("title_resource_uri");
        // Necessary to check for existence because we may be reading from an old DB version
        if (columnIndex > -1) {
            final String titleResourceUri = c.getString(columnIndex);
            if (titleResourceUri != null) {
                try {
                    title = getDefaultTitle(titleResourceUri);
                } catch (Exception e) {
                    // Best attempt only
                }
            }
        }
        if (title == null) {
            title = c.getString(c.getColumnIndex(MediaStore.Audio.Media.TITLE));
        }
        return title;
    }

    /**
     * @param title_resource_uri The title resource for which to retrieve the default localization
     * @return The title localized to {@code Locale.US}, or {@code null} if unlocalizable
     * @throws Exception Thrown if the title appears to be localizable, but the localization failed
     * for any reason. For example, the application from which the localized title is fetched is not
     * installed, or it does not have the resource which needs to be localized
     */
    private String getDefaultTitle(String title_resource_uri) throws Exception{
        try {
            return getTitleFromResourceUri(title_resource_uri, false);
        } catch (Exception e) {
            Log.e(TAG, "Error getting default title for " + title_resource_uri, e);
            throw e;
        }
    }

    /**
     * @param title_resource_uri The title resource to localize
     * @return The localized title, or {@code null} if unlocalizable
     * @throws Exception Thrown if the title appears to be localizable, but the localization failed
     * for any reason. For example, the application from which the localized title is fetched is not
     * installed, or it does not have the resource which needs to be localized
     */
    private String getLocalizedTitle(String title_resource_uri) throws Exception {
        try {
            return getTitleFromResourceUri(title_resource_uri, true);
        } catch (Exception e) {
            Log.e(TAG, "Error getting localized title for " + title_resource_uri, e);
            throw e;
        }
    }

    /**
     * Localizable titles conform to this URI pattern:
     *   Scheme: {@link ContentResolver.SCHEME_ANDROID_RESOURCE}
     *   Authority: Package Name of ringtone title provider
     *   First Path Segment: Type of resource (must be "string")
     *   Second Path Segment: Resource name of title
     *
     * @param title_resource_uri The title resource to retrieve
     * @param localize Whether or not to localize the title
     * @return The title, or {@code null} if unlocalizable
     * @throws Exception Thrown if the title appears to be localizable, but the localization failed
     * for any reason. For example, the application from which the localized title is fetched is not
     * installed, or it does not have the resource which needs to be localized
     */
    private String getTitleFromResourceUri(String title_resource_uri, boolean localize)
        throws Exception {
        if (TextUtils.isEmpty(title_resource_uri)) {
            return null;
        }
        final Uri titleUri = Uri.parse(title_resource_uri);
        final String scheme = titleUri.getScheme();
        if (!ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
            return null;
        }
        final List<String> pathSegments = titleUri.getPathSegments();
        if (pathSegments.size() != 2) {
            Log.e(TAG, "Error getting localized title for " + title_resource_uri
                + ", must have 2 path segments");
            return null;
        }
        final String type = pathSegments.get(0);
        if (!"string".equals(type)) {
            Log.e(TAG, "Error getting localized title for " + title_resource_uri
                + ", first path segment must be \"string\"");
            return null;
        }
        final String packageName = titleUri.getAuthority();
        final Resources resources;
        if (localize) {
            resources = mPackageManager.getResourcesForApplication(packageName);
        } else {
            final Context packageContext = getContext().createPackageContext(packageName, 0);
            final Configuration configuration = packageContext.getResources().getConfiguration();
            configuration.setLocale(Locale.US);
            resources = packageContext.createConfigurationContext(configuration).getResources();
        }
        final String resourceIdentifier = pathSegments.get(1);
        final int id = resources.getIdentifier(resourceIdentifier, type, packageName);
        return resources.getString(id);
    }

    public void onLocaleChanged() {
        onLocaleChanged(true);
    }

    private void onLocaleChanged(boolean forceUpdate) {
        mInternalDatabase.runWithTransaction((db) -> {
            if (forceUpdate || !mLastLocale.equals(Locale.getDefault())) {
                localizeTitles(db);
                mLastLocale = Locale.getDefault();
            }
            return null;
        });
    }

    private void localizeTitles(@NonNull SQLiteDatabase db) {
        try (Cursor c = db.query("files", new String[]{"_id", "title_resource_uri"},
            "title_resource_uri IS NOT NULL", null, null, null, null)) {
            while (c.moveToNext()) {
                final String id = c.getString(0);
                final String titleResourceUri = c.getString(1);
                final ContentValues values = new ContentValues();
                try {
                    values.put(AudioColumns.TITLE_RESOURCE_URI, titleResourceUri);
                    computeAudioLocalizedValues(values);
                    computeAudioKeyValues(values);
                    db.update("files", values, "_id=?", new String[]{id});
                } catch (Exception e) {
                    Log.e(TAG, "Error updating localized title for " + titleResourceUri
                        + ", keeping old localization");
                }
            }
        }
    }

    private Uri insertFile(@NonNull SQLiteQueryBuilder qb, @NonNull DatabaseHelper helper,
            int match, @NonNull Uri uri, @NonNull Bundle extras, @NonNull ContentValues values,
            int mediaType) throws VolumeArgumentException, VolumeNotFoundException {
        boolean wasPathEmpty = !values.containsKey(MediaStore.MediaColumns.DATA)
                || TextUtils.isEmpty(values.getAsString(MediaStore.MediaColumns.DATA));

        // Make sure all file-related columns are defined
        ensureUniqueFileColumns(match, uri, extras, values, null);

        switch (mediaType) {
            case FileColumns.MEDIA_TYPE_AUDIO: {
                computeAudioLocalizedValues(values);
                computeAudioKeyValues(values);
                break;
            }
        }

        // compute bucket_id and bucket_display_name for all files
        String path = values.getAsString(MediaStore.MediaColumns.DATA);
        FileUtils.computeValuesFromData(values, isFuseThread());
        values.put(MediaStore.MediaColumns.DATE_ADDED, System.currentTimeMillis() / 1000);

        String title = values.getAsString(MediaStore.MediaColumns.TITLE);
        if (title == null && path != null) {
            title = extractFileName(path);
        }
        values.put(FileColumns.TITLE, title);

        String mimeType = null;
        int format = MtpConstants.FORMAT_ASSOCIATION;
        if (path != null && new File(path).isDirectory()) {
            values.put(FileColumns.FORMAT, MtpConstants.FORMAT_ASSOCIATION);
            values.putNull(MediaStore.MediaColumns.MIME_TYPE);
        } else {
            mimeType = values.getAsString(MediaStore.MediaColumns.MIME_TYPE);
            final Integer formatObject = values.getAsInteger(FileColumns.FORMAT);
            format = (formatObject == null ? 0 : formatObject.intValue());
        }

        if (format == 0) {
            format = MimeUtils.resolveFormatCode(mimeType);
        }
        if (path != null && path.endsWith("/")) {
            // TODO: convert to using FallbackException once VERSION_CODES.S is defined
            Log.e(TAG, "directory has trailing slash: " + path);
            return null;
        }
        if (format != 0) {
            values.put(FileColumns.FORMAT, format);
        }

        if (mimeType == null && path != null && format != MtpConstants.FORMAT_ASSOCIATION) {
            mimeType = MimeUtils.resolveMimeType(new File(path));
        }

        if (mimeType != null) {
            values.put(FileColumns.MIME_TYPE, mimeType);
            if (isCallingPackageSelf() && values.containsKey(FileColumns.MEDIA_TYPE)) {
                // Leave FileColumns.MEDIA_TYPE untouched if the caller is ModernMediaScanner and
                // FileColumns.MEDIA_TYPE is already populated.
            } else if (isFuseThread() && path != null
                    && FileUtils.shouldFileBeHidden(new File(path))) {
                // We should only mark MEDIA_TYPE as MEDIA_TYPE_NONE for Fuse Thread.
                // MediaProvider#insert() returns the uri by appending the "rowId" to the given
                // uri, hence to ensure the correct working of the returned uri, we shouldn't
                // change the MEDIA_TYPE in insert operation and let scan change it for us.
                values.put(FileColumns.MEDIA_TYPE, FileColumns.MEDIA_TYPE_NONE);
            } else {
                values.put(FileColumns.MEDIA_TYPE, MimeUtils.resolveMediaType(mimeType));
            }
        } else {
            values.put(FileColumns.MEDIA_TYPE, mediaType);
        }

        qb.allowColumn(FileColumns._MODIFIER);
        if (isCallingPackageSelf() && values.containsKey(FileColumns._MODIFIER)) {
            // We can't identify if the call is coming from media scan, hence
            // we let ModernMediaScanner send FileColumns._MODIFIER value.
        } else if (isFuseThread()) {
            values.put(FileColumns._MODIFIER, FileColumns._MODIFIER_FUSE);
        } else {
            values.put(FileColumns._MODIFIER, FileColumns._MODIFIER_CR);
        }

        // There is no meaning of an owner in the internal storage. It is shared by all users.
        // So we only set the user_id field in the database for external storage.
        qb.allowColumn(FileColumns._USER_ID);
        int ownerUserId = FileUtils.extractUserId(path);
        if (helper.isExternal()) {
            if (isAppCloneUserForFuse(ownerUserId)) {
                values.put(FileColumns._USER_ID, ownerUserId);
            } else {
                values.put(FileColumns._USER_ID, sUserId);
            }
        }

        final long rowId;
        Uri newUri = uri;
        {
            if (mediaType == FileColumns.MEDIA_TYPE_PLAYLIST) {
                String name = values.getAsString(Audio.Playlists.NAME);
                if (name == null && path == null) {
                    // MediaScanner will compute the name from the path if we have one
                    throw new IllegalArgumentException(
                            "no name was provided when inserting abstract playlist");
                }
            } else {
                if (path == null) {
                    // path might be null for playlists created on the device
                    // or transfered via MTP
                    throw new IllegalArgumentException(
                            "no path was provided when inserting new file");
                }
            }

            // make sure modification date and size are set
            if (path != null) {
                File file = new File(path);
                if (file.exists()) {
                    values.put(FileColumns.DATE_MODIFIED, file.lastModified() / 1000);
                    if (!values.containsKey(FileColumns.SIZE)) {
                        values.put(FileColumns.SIZE, file.length());
                    }
                }
                // Checking if the file/directory is hidden can be expensive based on the depth of
                // the directory tree. Call shouldFileBeHidden() only when the caller of insert()
                // cares about returned uri.
                if (!isCallingPackageSelf() && !isFuseThread()
                        && FileUtils.shouldFileBeHidden(file)) {
                    newUri = MediaStore.Files.getContentUri(MediaStore.getVolumeName(uri));
                }
            }

            rowId = insertAllowingUpsert(qb, helper, values, path);
        }
        if (format == MtpConstants.FORMAT_ASSOCIATION) {
            synchronized (mDirectoryCache) {
                mDirectoryCache.put(path, rowId);
            }
        }

        return ContentUris.withAppendedId(newUri, rowId);
    }

    /**
     * Inserts a new row in MediaProvider database with {@code values}. Treats insert as upsert for
     * double inserts from same package.
     */
    private long insertAllowingUpsert(@NonNull SQLiteQueryBuilder qb,
            @NonNull DatabaseHelper helper, @NonNull ContentValues values, String path)
            throws SQLiteConstraintException {
        return helper.runWithTransaction((db) -> {
            Long parent = values.getAsLong(FileColumns.PARENT);
            if (parent == null) {
                if (path != null) {
                    final long parentId = getParent(db, path);
                    values.put(FileColumns.PARENT, parentId);
                }
            }

            try {
                return qb.insert(helper, values);
            } catch (SQLiteConstraintException e) {
                final String packages = getAllowedPackagesForUpsert(
                        values.getAsString(MediaColumns.OWNER_PACKAGE_NAME));
                SQLiteQueryBuilder qbForUpsert = getQueryBuilderForUpsert(path);
                final long rowId = getIdIfPathOwnedByPackages(qbForUpsert, helper, path, packages);
                // Apps sometimes create a file via direct path and then insert it into
                // MediaStore via ContentResolver. The former should create a database entry,
                // so we have to treat the latter as an upsert.
                // TODO(b/149917493) Perform all INSERT operations as UPSERT.
                if (rowId != -1 && qbForUpsert.update(helper, values, "_id=?",
                        new String[]{Long.toString(rowId)}) == 1) {
                    return rowId;
                }
                // Rethrow SQLiteConstraintException on failed upsert.
                throw e;
            }
        });
    }

    /**
     * @return row id of the entry with path {@code path} if the owner is one of {@code packages}.
     */
    private long getIdIfPathOwnedByPackages(@NonNull SQLiteQueryBuilder qb,
            @NonNull DatabaseHelper helper, String path, String packages) {
        final String[] projection = new String[] {FileColumns._ID};
        final  String ownerPackageMatchClause = DatabaseUtils.bindSelection(
                MediaColumns.OWNER_PACKAGE_NAME + " IN " + packages);
        final String selection = FileColumns.DATA + " =? AND " + ownerPackageMatchClause;

        try (Cursor c = qb.query(helper, projection, selection, new String[] {path}, null, null,
                null, null, null)) {
            if (c.moveToFirst()) {
                return c.getLong(0);
            }
        }
        return -1;
    }

    /**
     * Gets packages that should match to upsert a db row.
     *
     * A database row can be upserted if
     * <ul>
     * <li> Calling package or one of the shared packages owns the db row.
     * <li> {@code givenOwnerPackage} owns the db row. This is useful when DownloadProvider
     * requests upsert on behalf of another app
     * </ul>
     */
    private String getAllowedPackagesForUpsert(@Nullable String givenOwnerPackage) {
        ArrayList<String> packages = new ArrayList<>();
        packages.addAll(Arrays.asList(mCallingIdentity.get().getSharedPackageNames()));

        // If givenOwnerPackage is CallingIdentity, packages list would already have shared package
        // names of givenOwnerPackage. If givenOwnerPackage is not CallingIdentity, since
        // DownloadProvider can upsert a row on behalf of app, we should include all shared packages
        // of givenOwnerPackage.
        if (givenOwnerPackage != null && isCallingPackageDelegator() &&
                !isCallingIdentitySharedPackageName(givenOwnerPackage)) {
            // Allow DownloadProvider to Upsert if givenOwnerPackage is owner of the db row.
            packages.addAll(Arrays.asList(getSharedPackagesForPackage(givenOwnerPackage)));
        }
        return bindList((Object[]) packages.toArray());
    }

    /**
     * @return {@link SQLiteQueryBuilder} for upsert with Files uri. This disables strict columns
     * check to allow upsert to update any column with Files uri.
     */
    private SQLiteQueryBuilder getQueryBuilderForUpsert(@NonNull String path) {
        final boolean allowHidden = isCallingPackageAllowedHidden();
        Bundle extras = new Bundle();
        extras.putInt(QUERY_ARG_MATCH_PENDING, MATCH_INCLUDE);
        extras.putInt(QUERY_ARG_MATCH_TRASHED, MATCH_INCLUDE);

        // When Fuse inserts a file to database it doesn't set is_download column. When app tries
        // insert with Downloads uri, upsert fails because getIdIfPathExistsForCallingPackage can't
        // find a row ID with is_download=1. Use Files uri to get queryBuilder & update any existing
        // row irrespective of is_download=1.
        final Uri uri = FileUtils.getContentUriForPath(path);
        SQLiteQueryBuilder qb = getQueryBuilder(TYPE_UPDATE, matchUri(uri, allowHidden), uri,
                extras, null);

        // We won't be able to update columns that are not part of projection map of Files table. We
        // have already checked strict columns in previous insert operation which failed with
        // exception. Any malicious column usage would have got caught in insert operation, hence we
        // can safely disable strict column check for upsert.
        qb.setStrictColumns(false);
        return qb;
    }

    private void maybePut(@NonNull ContentValues values, @NonNull String key,
            @Nullable String value) {
        if (value != null) {
            values.put(key, value);
        }
    }

    private boolean maybeMarkAsDownload(@NonNull ContentValues values) {
        final String path = values.getAsString(MediaColumns.DATA);
        if (path != null && isDownload(path)) {
            values.put(FileColumns.IS_DOWNLOAD, 1);
            return true;
        }
        return false;
    }

    private static @NonNull String resolveVolumeName(@NonNull Uri uri) {
        final String volumeName = getVolumeName(uri);
        if (MediaStore.VOLUME_EXTERNAL.equals(volumeName)) {
            return MediaStore.VOLUME_EXTERNAL_PRIMARY;
        } else {
            return volumeName;
        }
    }

    /**
     * @deprecated all operations should be routed through the overload that
     *             accepts a {@link Bundle} of extras.
     */
    @Override
    @Deprecated
    public Uri insert(Uri uri, ContentValues values) {
        return insert(uri, values, null);
    }

    @Override
    public @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values,
            @Nullable Bundle extras) {
        Trace.beginSection("insert");
        try {
            try {
                return insertInternal(uri, values, extras);
            } catch (SQLiteConstraintException e) {
                if (getCallingPackageTargetSdkVersion() >= Build.VERSION_CODES.R) {
                    throw e;
                } else {
                    return null;
                }
            }
        } catch (FallbackException e) {
            return e.translateForInsert(getCallingPackageTargetSdkVersion());
        } finally {
            Trace.endSection();
        }
    }

    private @Nullable Uri insertInternal(@NonNull Uri uri, @Nullable ContentValues initialValues,
            @Nullable Bundle extras) throws FallbackException {
        final String originalVolumeName = getVolumeName(uri);
        PulledMetrics.logVolumeAccessViaMediaProvider(getCallingUidOrSelf(), originalVolumeName);

        extras = (extras != null) ? extras : new Bundle();
        // REDACTED_URI_BUNDLE_KEY extra should only be set inside MediaProvider.
        extras.remove(QUERY_ARG_REDACTED_URI);

        // INCLUDED_DEFAULT_DIRECTORIES extra should only be set inside MediaProvider.
        extras.remove(INCLUDED_DEFAULT_DIRECTORIES);

        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        final int targetSdkVersion = getCallingPackageTargetSdkVersion();
        final String resolvedVolumeName = resolveVolumeName(uri);

        // handle MEDIA_SCANNER before calling getDatabaseForUri()
        if (match == MEDIA_SCANNER) {
            mMediaScannerVolume = initialValues.getAsString(MediaStore.MEDIA_SCANNER_VOLUME);

            final DatabaseHelper helper = getDatabaseForUri(
                    MediaStore.Files.getContentUri(mMediaScannerVolume));

            helper.mScanStartTime = SystemClock.elapsedRealtime();
            return MediaStore.getMediaScannerUri();
        }

        if (match == VOLUMES) {
            String name = initialValues.getAsString("name");
            MediaVolume volume = null;
            try {
                volume = getVolume(name);
                Uri attachedVolume = attachVolume(volume, /* validate */ true);
                if (mMediaScannerVolume != null && mMediaScannerVolume.equals(name)) {
                    final DatabaseHelper helper = getDatabaseForUri(
                            MediaStore.Files.getContentUri(mMediaScannerVolume));
                    helper.mScanStartTime = SystemClock.elapsedRealtime();
                }
                return attachedVolume;
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Couldn't find volume with name " + volume.getName());
                return null;
            }
        }

        final DatabaseHelper helper = getDatabaseForUri(uri);
        switch (match) {
            case AUDIO_PLAYLISTS_ID:
            case AUDIO_PLAYLISTS_ID_MEMBERS: {
                final long playlistId = Long.parseLong(uri.getPathSegments().get(3));
                final Uri playlistUri = ContentUris.withAppendedId(
                        MediaStore.Audio.Playlists.getContentUri(resolvedVolumeName), playlistId);

                final long audioId = initialValues
                        .getAsLong(MediaStore.Audio.Playlists.Members.AUDIO_ID);
                final String audioVolumeName =
                        MediaStore.VOLUME_INTERNAL.equals(resolvedVolumeName)
                                ? MediaStore.VOLUME_INTERNAL : MediaStore.VOLUME_EXTERNAL;
                final Uri audioUri = ContentUris.withAppendedId(
                        MediaStore.Audio.Media.getContentUri(audioVolumeName), audioId);

                // Require that caller has write access to underlying media
                enforceCallingPermission(playlistUri, Bundle.EMPTY, true);
                enforceCallingPermission(audioUri, Bundle.EMPTY, false);

                // Playlist contents are always persisted directly into playlist
                // files on disk to ensure that we can reliably migrate between
                // devices and recover from database corruption
                final long id = addPlaylistMembers(playlistUri, initialValues);
                acceptWithExpansion(helper::notifyInsert, resolvedVolumeName, playlistId,
                        FileColumns.MEDIA_TYPE_PLAYLIST, false);
                return ContentUris.withAppendedId(MediaStore.Audio.Playlists.Members
                        .getContentUri(originalVolumeName, playlistId), id);
            }
        }

        String path = null;
        String ownerPackageName = null;
        if (initialValues != null) {
            // IDs are forever; nobody should be editing them
            initialValues.remove(MediaColumns._ID);

            // Expiration times are hard-coded; let's derive them
            FileUtils.computeDateExpires(initialValues);

            // Ignore or augment incoming raw filesystem paths
            for (String column : sDataColumns.keySet()) {
                if (!initialValues.containsKey(column)) continue;

                if (isCallingPackageSelf() || isCallingPackageLegacyWrite()) {
                    // Mutation allowed
                } else if (isCallingPackageManager()) {
                    // Apps with MANAGE_EXTERNAL_STORAGE have all files access, hence they are
                    // allowed to insert files anywhere.
                } else {
                    Log.w(TAG, "Ignoring mutation of  " + column + " from "
                            + getCallingPackageOrSelf());
                    initialValues.remove(column);
                }
            }

            path = initialValues.getAsString(MediaStore.MediaColumns.DATA);

            if (!isCallingPackageSelf()) {
                initialValues.remove(FileColumns.IS_DOWNLOAD);
            }

            // We no longer track location metadata
            if (initialValues.containsKey(ImageColumns.LATITUDE)) {
                initialValues.putNull(ImageColumns.LATITUDE);
            }
            if (initialValues.containsKey(ImageColumns.LONGITUDE)) {
                initialValues.putNull(ImageColumns.LONGITUDE);
            }
            if (getCallingPackageTargetSdkVersion() <= Build.VERSION_CODES.Q) {
                // These columns are removed in R.
                if (initialValues.containsKey("primary_directory")) {
                    initialValues.remove("primary_directory");
                }
                if (initialValues.containsKey("secondary_directory")) {
                    initialValues.remove("secondary_directory");
                }
            }

            if (isCallingPackageSelf() || isCallingPackageShell()) {
                // When media inserted by ourselves during a scan, or by the
                // shell, the best we can do is guess ownership based on path
                // when it's not explicitly provided
                ownerPackageName = initialValues.getAsString(FileColumns.OWNER_PACKAGE_NAME);
                if (TextUtils.isEmpty(ownerPackageName)) {
                    ownerPackageName = extractPathOwnerPackageName(path);
                }
            } else if (isCallingPackageDelegator()) {
                // When caller is a delegator, we handle ownership as a hybrid
                // of the two other cases: we're willing to accept any ownership
                // transfer attempted during insert, but we fall back to using
                // the Binder identity if they don't request a specific owner
                ownerPackageName = initialValues.getAsString(FileColumns.OWNER_PACKAGE_NAME);
                if (TextUtils.isEmpty(ownerPackageName)) {
                    ownerPackageName = getCallingPackageOrSelf();
                }
            } else {
                // Remote callers have no direct control over owner column; we force
                // it be whoever is creating the content.
                initialValues.remove(FileColumns.OWNER_PACKAGE_NAME);
                ownerPackageName = getCallingPackageOrSelf();
            }
        }

        long rowId = -1;
        Uri newUri = null;

        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_INSERT, match, uri, extras, null);

        switch (match) {
            case IMAGES_MEDIA: {
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                final boolean isDownload = maybeMarkAsDownload(initialValues);
                newUri = insertFile(qb, helper, match, uri, extras, initialValues,
                        FileColumns.MEDIA_TYPE_IMAGE);
                break;
            }

            case IMAGES_THUMBNAILS: {
                if (helper.isInternal()) {
                    throw new UnsupportedOperationException(
                            "Writing to internal storage is not supported.");
                }

                // Require that caller has write access to underlying media
                final long imageId = initialValues.getAsLong(MediaStore.Images.Thumbnails.IMAGE_ID);
                enforceCallingPermission(ContentUris.withAppendedId(
                        MediaStore.Images.Media.getContentUri(resolvedVolumeName), imageId),
                        extras, true);

                ensureUniqueFileColumns(match, uri, extras, initialValues, null);

                rowId = qb.insert(helper, initialValues);
                if (rowId > 0) {
                    newUri = ContentUris.withAppendedId(Images.Thumbnails.
                            getContentUri(originalVolumeName), rowId);
                }
                break;
            }

            case VIDEO_THUMBNAILS: {
                if (helper.isInternal()) {
                    throw new UnsupportedOperationException(
                            "Writing to internal storage is not supported.");
                }

                // Require that caller has write access to underlying media
                final long videoId = initialValues.getAsLong(MediaStore.Video.Thumbnails.VIDEO_ID);
                enforceCallingPermission(ContentUris.withAppendedId(
                        MediaStore.Video.Media.getContentUri(resolvedVolumeName), videoId),
                        Bundle.EMPTY, true);

                ensureUniqueFileColumns(match, uri, extras, initialValues, null);

                rowId = qb.insert(helper, initialValues);
                if (rowId > 0) {
                    newUri = ContentUris.withAppendedId(Video.Thumbnails.
                            getContentUri(originalVolumeName), rowId);
                }
                break;
            }

            case AUDIO_MEDIA: {
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                final boolean isDownload = maybeMarkAsDownload(initialValues);
                newUri = insertFile(qb, helper, match, uri, extras, initialValues,
                        FileColumns.MEDIA_TYPE_AUDIO);
                break;
            }

            case AUDIO_MEDIA_ID_GENRES: {
                throw new FallbackException("Genres are read-only", Build.VERSION_CODES.R);
            }

            case AUDIO_GENRES: {
                throw new FallbackException("Genres are read-only", Build.VERSION_CODES.R);
            }

            case AUDIO_GENRES_ID_MEMBERS: {
                throw new FallbackException("Genres are read-only", Build.VERSION_CODES.R);
            }

            case AUDIO_PLAYLISTS: {
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                final boolean isDownload = maybeMarkAsDownload(initialValues);
                ContentValues values = new ContentValues(initialValues);
                values.put(MediaStore.Audio.Playlists.DATE_ADDED, System.currentTimeMillis() / 1000);
                // Playlist names are stored as display names, but leave
                // values untouched if the caller is ModernMediaScanner
                if (!isCallingPackageSelf()) {
                    if (values.containsKey(Playlists.NAME)) {
                        values.put(MediaColumns.DISPLAY_NAME, values.getAsString(Playlists.NAME));
                    }
                    if (!values.containsKey(MediaColumns.MIME_TYPE)) {
                        values.put(MediaColumns.MIME_TYPE, "audio/mpegurl");
                    }
                }
                newUri = insertFile(qb, helper, match, uri, extras, values,
                        FileColumns.MEDIA_TYPE_PLAYLIST);
                if (newUri != null) {
                    // Touch empty playlist file on disk so its ready for renames
                    if (Binder.getCallingUid() != android.os.Process.myUid()) {
                        try (OutputStream out = ContentResolver.wrap(this)
                                .openOutputStream(newUri)) {
                        } catch (IOException ignored) {
                        }
                    }
                }
                break;
            }

            case VIDEO_MEDIA: {
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                final boolean isDownload = maybeMarkAsDownload(initialValues);
                newUri = insertFile(qb, helper, match, uri, extras, initialValues,
                        FileColumns.MEDIA_TYPE_VIDEO);
                break;
            }

            case AUDIO_ALBUMART: {
                if (helper.isInternal()) {
                    throw new UnsupportedOperationException("no internal album art allowed");
                }

                ensureUniqueFileColumns(match, uri, extras, initialValues, null);

                rowId = qb.insert(helper, initialValues);
                if (rowId > 0) {
                    newUri = ContentUris.withAppendedId(uri, rowId);
                }
                break;
            }

            case FILES: {
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                final boolean isDownload = maybeMarkAsDownload(initialValues);
                final String mimeType = initialValues.getAsString(MediaColumns.MIME_TYPE);
                final int mediaType = MimeUtils.resolveMediaType(mimeType);
                newUri = insertFile(qb, helper, match, uri, extras, initialValues,
                        mediaType);
                break;
            }

            case DOWNLOADS:
                maybePut(initialValues, FileColumns.OWNER_PACKAGE_NAME, ownerPackageName);
                initialValues.put(FileColumns.IS_DOWNLOAD, 1);
                newUri = insertFile(qb, helper, match, uri, extras, initialValues,
                        FileColumns.MEDIA_TYPE_NONE);
                break;

            default:
                throw new UnsupportedOperationException("Invalid URI " + uri);
        }

        // Remember that caller is owner of this item, to speed up future
        // permission checks for this caller
        mCallingIdentity.get().setOwned(rowId, true);

        if (path != null && path.toLowerCase(Locale.ROOT).endsWith("/.nomedia")) {
            scanFileAsMediaProvider(new File(path).getParentFile(), REASON_DEMAND);
        }

        return newUri;
    }

    @Override
    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
                throws OperationApplicationException {
        // Open transactions on databases for requested volumes
        final Set<DatabaseHelper> transactions = new ArraySet<>();
        try {
            for (ContentProviderOperation op : operations) {
                final DatabaseHelper helper = getDatabaseForUri(op.getUri());
                if (transactions.contains(helper)) continue;

                if (!helper.isTransactionActive()) {
                    helper.beginTransaction();
                    transactions.add(helper);
                } else {
                    // We normally don't allow nested transactions (since we
                    // don't have a good way to selectively roll them back) but
                    // if the incoming operation is ignoring exceptions, then we
                    // don't need to worry about partial rollback and can
                    // piggyback on the larger active transaction
                    if (!op.isExceptionAllowed()) {
                        throw new IllegalStateException("Nested transactions not supported");
                    }
                }
            }

            final ContentProviderResult[] result = super.applyBatch(operations);
            for (DatabaseHelper helper : transactions) {
                helper.setTransactionSuccessful();
            }
            return result;
        } catch (VolumeNotFoundException e) {
            throw e.rethrowAsIllegalArgumentException();
        } finally {
            for (DatabaseHelper helper : transactions) {
                helper.endTransaction();
            }
        }
    }

    private void appendWhereStandaloneMatch(@NonNull SQLiteQueryBuilder qb,
            @NonNull String column, /* @Match */ int match, Uri uri) {
        switch (match) {
            case MATCH_INCLUDE:
                // No special filtering needed
                break;
            case MATCH_EXCLUDE:
                appendWhereStandalone(qb, getWhereClauseForMatchExclude(column));
                break;
            case MATCH_ONLY:
                appendWhereStandalone(qb, column + "=?", 1);
                break;
            case MATCH_VISIBLE_FOR_FILEPATH:
                final String whereClause =
                        getWhereClauseForMatchableVisibleFromFilePath(uri, column);
                if (whereClause != null) {
                    appendWhereStandalone(qb, whereClause);
                }
                break;
            default:
                throw new IllegalArgumentException();
        }
    }

    private static void appendWhereStandalone(@NonNull SQLiteQueryBuilder qb,
            @Nullable String selection, @Nullable Object... selectionArgs) {
        qb.appendWhereStandalone(DatabaseUtils.bindSelection(selection, selectionArgs));
    }

    private static void appendWhereStandaloneFilter(@NonNull SQLiteQueryBuilder qb,
            @NonNull String[] columns, @Nullable String filter) {
        if (TextUtils.isEmpty(filter)) return;
        for (String filterWord : filter.split("\\s+")) {
            appendWhereStandalone(qb, String.join("||", columns) + " LIKE ? ESCAPE '\\'",
                    "%" + DatabaseUtils.escapeForLike(Audio.keyFor(filterWord)) + "%");
        }
    }

    /**
     * Gets {@link LocalCallingIdentity} for the calling package
     * TODO(b/170465810) Change the method name after refactoring.
     */
    LocalCallingIdentity getCachedCallingIdentityForTranscoding(int uid) {
        return getCachedCallingIdentityForFuse(uid);
    }

    @Deprecated
    private String getSharedPackages() {
        final String[] sharedPackageNames = mCallingIdentity.get().getSharedPackageNames();
        return bindList((Object[]) sharedPackageNames);
    }

    /**
     * Gets shared packages names for given {@code packageName}
     */
    private String[] getSharedPackagesForPackage(String packageName) {
        try {
            final int packageUid = getContext().getPackageManager()
                    .getPackageUid(packageName, 0);
            return getContext().getPackageManager().getPackagesForUid(packageUid);
        } catch (NameNotFoundException ignored) {
            return new String[] {packageName};
        }
    }

    private static final int TYPE_QUERY = 0;
    private static final int TYPE_INSERT = 1;
    private static final int TYPE_UPDATE = 2;
    private static final int TYPE_DELETE = 3;

    /**
     * Creating a new method for Transcoding to avoid any merge conflicts.
     * TODO(b/170465810): Remove this when getQueryBuilder code is refactored.
     */
    @NonNull SQLiteQueryBuilder getQueryBuilderForTranscoding(int type, int match,
            @NonNull Uri uri, @NonNull Bundle extras, @Nullable Consumer<String> honored) {
        // Force MediaProvider calling identity when accessing the db from transcoding to avoid
        // generating 'strict' SQL e.g forcing owner_package_name matches
        // We already handle the required permission checks for the app before we get here
        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try {
            return getQueryBuilder(type, match, uri, extras, honored);
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    /**
     * Generate a {@link SQLiteQueryBuilder} that is filtered based on the
     * runtime permissions and/or {@link Uri} grants held by the caller.
     * <ul>
     * <li>If caller holds a {@link Uri} grant, access is allowed according to
     * that grant.
     * <li>If caller holds the write permission for a collection, they can
     * read/write all contents of that collection.
     * <li>If caller holds the read permission for a collection, they can read
     * all contents of that collection, but writes are limited to content they
     * own.
     * <li>If caller holds no permissions for a collection, all reads/write are
     * limited to content they own.
     * </ul>
     */
    private @NonNull SQLiteQueryBuilder getQueryBuilder(int type, int match,
            @NonNull Uri uri, @NonNull Bundle extras, @Nullable Consumer<String> honored) {
        Trace.beginSection("getQueryBuilder");
        try {
            return getQueryBuilderInternal(type, match, uri, extras, honored);
        } finally {
            Trace.endSection();
        }
    }

    private @NonNull SQLiteQueryBuilder getQueryBuilderInternal(int type, int match,
            @NonNull Uri uri, @NonNull Bundle extras, @Nullable Consumer<String> honored) {
        final boolean forWrite;
        switch (type) {
            case TYPE_QUERY: forWrite = false; break;
            case TYPE_INSERT: forWrite = true; break;
            case TYPE_UPDATE: forWrite = true; break;
            case TYPE_DELETE: forWrite = true; break;
            default: throw new IllegalStateException();
        }

        final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        if (uri.getBooleanQueryParameter("distinct", false)) {
            qb.setDistinct(true);
        }
        qb.setStrict(true);
        if (isCallingPackageSelf()) {
            // When caller is system, such as the media scanner, we're willing
            // to let them access any columns they want
        } else {
            qb.setTargetSdkVersion(getCallingPackageTargetSdkVersion());
            qb.setStrictColumns(true);
            qb.setStrictGrammar(true);
        }

        // TODO: throw when requesting a currently unmounted volume
        final String volumeName = MediaStore.getVolumeName(uri);
        final String includeVolumes;
        if (MediaStore.VOLUME_EXTERNAL.equals(volumeName)) {
            includeVolumes = bindList(mVolumeCache.getExternalVolumeNames().toArray());
        } else {
            includeVolumes = bindList(volumeName);
        }
        final String sharedPackages = getSharedPackages();
        final String matchSharedPackagesClause = FileColumns.OWNER_PACKAGE_NAME + " IN "
                + sharedPackages;

        boolean allowGlobal;
        final Uri redactedUri = extras.getParcelable(QUERY_ARG_REDACTED_URI);
        if (redactedUri != null) {
            if (forWrite) {
                throw new UnsupportedOperationException(
                        "Writes on: " + redactedUri.toString() + " are not supported");
            }
            allowGlobal = checkCallingPermissionGlobal(redactedUri, false);
        } else {
            allowGlobal = checkCallingPermissionGlobal(uri, forWrite);
        }

        final boolean allowLegacy =
                forWrite ? isCallingPackageLegacyWrite() : isCallingPackageLegacyRead();
        final boolean allowLegacyRead = allowLegacy && !forWrite;

        int matchPending = extras.getInt(QUERY_ARG_MATCH_PENDING, MATCH_DEFAULT);
        int matchTrashed = extras.getInt(QUERY_ARG_MATCH_TRASHED, MATCH_DEFAULT);
        int matchFavorite = extras.getInt(QUERY_ARG_MATCH_FAVORITE, MATCH_DEFAULT);

        final ArrayList<String> includedDefaultDirs = extras.getStringArrayList(
                INCLUDED_DEFAULT_DIRECTORIES);

        // Handle callers using legacy arguments
        if (MediaStore.getIncludePending(uri)) matchPending = MATCH_INCLUDE;

        // Resolve any remaining default options
        final int defaultMatchForPendingAndTrashed;
        if (isFuseThread()) {
            // Write operations always check for file ownership, we don't need additional write
            // permission check for is_pending and is_trashed.
            defaultMatchForPendingAndTrashed =
                    forWrite ? MATCH_INCLUDE : MATCH_VISIBLE_FOR_FILEPATH;
        } else {
            defaultMatchForPendingAndTrashed = MATCH_EXCLUDE;
        }
        if (matchPending == MATCH_DEFAULT) matchPending = defaultMatchForPendingAndTrashed;
        if (matchTrashed == MATCH_DEFAULT) matchTrashed = defaultMatchForPendingAndTrashed;
        if (matchFavorite == MATCH_DEFAULT) matchFavorite = MATCH_INCLUDE;

        // Handle callers using legacy filtering
        final String filter = uri.getQueryParameter("filter");

        // Only accept ALL_VOLUMES parameter up until R, because we're not convinced we want
        // to commit to this as an API.
        final boolean includeAllVolumes = shouldIncludeRecentlyUnmountedVolumes(uri, extras);
        final String callingPackage = getCallingPackageOrSelf();

        switch (match) {
            case IMAGES_MEDIA_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case IMAGES_MEDIA: {
                if (type == TYPE_QUERY) {
                    qb.setTables("images");
                    qb.setProjectionMap(
                            getProjectionMap(Images.Media.class));
                } else {
                    qb.setTables("files");
                    qb.setProjectionMap(
                            getProjectionMap(Images.Media.class, Files.FileColumns.class));
                    appendWhereStandalone(qb, FileColumns.MEDIA_TYPE + "=?",
                            FileColumns.MEDIA_TYPE_IMAGE);
                }
                if (!allowGlobal && !checkCallingPermissionImages(forWrite, callingPackage)) {
                    appendWhereStandalone(qb, matchSharedPackagesClause);
                }
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case IMAGES_THUMBNAILS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                // fall-through
            case IMAGES_THUMBNAILS: {
                qb.setTables("thumbnails");

                final ArrayMap<String, String> projectionMap = new ArrayMap<>(
                        getProjectionMap(Images.Thumbnails.class));
                projectionMap.put(Images.Thumbnails.THUMB_DATA,
                        "NULL AS " + Images.Thumbnails.THUMB_DATA);
                qb.setProjectionMap(projectionMap);

                if (!allowGlobal && !checkCallingPermissionImages(forWrite, callingPackage)) {
                    appendWhereStandalone(qb,
                            "image_id IN (SELECT _id FROM images WHERE "
                                    + matchSharedPackagesClause + ")");
                }
                break;
            }
            case AUDIO_MEDIA_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case AUDIO_MEDIA: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio");
                    qb.setProjectionMap(
                            getProjectionMap(Audio.Media.class));
                } else {
                    qb.setTables("files");
                    qb.setProjectionMap(
                            getProjectionMap(Audio.Media.class, Files.FileColumns.class));
                    appendWhereStandalone(qb, FileColumns.MEDIA_TYPE + "=?",
                            FileColumns.MEDIA_TYPE_AUDIO);
                }
                if (!allowGlobal && !checkCallingPermissionAudio(forWrite, callingPackage)) {
                    // Apps without Audio permission can only see their own
                    // media, but we also let them see ringtone-style media to
                    // support legacy use-cases.
                    appendWhereStandalone(qb,
                            DatabaseUtils.bindSelection(matchSharedPackagesClause
                                    + " OR is_ringtone=1 OR is_alarm=1 OR is_notification=1"));
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY, AudioColumns.ALBUM_KEY, AudioColumns.TITLE_KEY
                }, filter);
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case AUDIO_MEDIA_ID_GENRES_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(5));
                // fall-through
            case AUDIO_MEDIA_ID_GENRES: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_genres");
                    qb.setProjectionMap(getProjectionMap(Audio.Genres.class));
                } else {
                    throw new UnsupportedOperationException("Genres cannot be directly modified");
                }
                appendWhereStandalone(qb, "_id IN (SELECT genre_id FROM " +
                        "audio WHERE _id=?)", uri.getPathSegments().get(3));
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_GENRES_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                // fall-through
            case AUDIO_GENRES: {
                qb.setTables("audio_genres");
                qb.setProjectionMap(getProjectionMap(Audio.Genres.class));
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_GENRES_ID_MEMBERS:
                appendWhereStandalone(qb, "genre_id=?", uri.getPathSegments().get(3));
                // fall-through
            case AUDIO_GENRES_ALL_MEMBERS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio");

                    final ArrayMap<String, String> projectionMap = new ArrayMap<>(
                            getProjectionMap(Audio.Genres.Members.class));
                    projectionMap.put(Audio.Genres.Members.AUDIO_ID,
                            "_id AS " + Audio.Genres.Members.AUDIO_ID);
                    qb.setProjectionMap(projectionMap);
                } else {
                    throw new UnsupportedOperationException("Genres cannot be directly modified");
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY, AudioColumns.ALBUM_KEY, AudioColumns.TITLE_KEY
                }, filter);
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                // In order to be consistent with other audio views like audio_artist, audio_albums,
                // and audio_genres, exclude pending and trashed item
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, MATCH_EXCLUDE, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, MATCH_EXCLUDE, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case AUDIO_PLAYLISTS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case AUDIO_PLAYLISTS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_playlists");
                    qb.setProjectionMap(
                            getProjectionMap(Audio.Playlists.class));
                } else {
                    qb.setTables("files");
                    qb.setProjectionMap(
                            getProjectionMap(Audio.Playlists.class, Files.FileColumns.class));
                    appendWhereStandalone(qb, FileColumns.MEDIA_TYPE + "=?",
                            FileColumns.MEDIA_TYPE_PLAYLIST);
                }
                if (!allowGlobal && !checkCallingPermissionAudio(forWrite, callingPackage)) {
                    appendWhereStandalone(qb, matchSharedPackagesClause);
                }
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case AUDIO_PLAYLISTS_ID_MEMBERS_ID:
                appendWhereStandalone(qb, "audio_playlists_map._id=?",
                        uri.getPathSegments().get(5));
                // fall-through
            case AUDIO_PLAYLISTS_ID_MEMBERS: {
                appendWhereStandalone(qb, "playlist_id=?", uri.getPathSegments().get(3));
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_playlists_map, audio");

                    final ArrayMap<String, String> projectionMap = new ArrayMap<>(
                            getProjectionMap(Audio.Playlists.Members.class));
                    projectionMap.put(Audio.Playlists.Members._ID,
                            "audio_playlists_map._id AS " + Audio.Playlists.Members._ID);
                    qb.setProjectionMap(projectionMap);

                    appendWhereStandalone(qb, "audio._id = audio_id");
                    // Since we use audio table along with audio_playlists_map
                    // for querying, we should only include database rows of
                    // the attached volumes.
                    if (!includeAllVolumes) {
                        appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN "
                             + includeVolumes);
                    }
                } else {
                    qb.setTables("audio_playlists_map");
                    qb.setProjectionMap(getProjectionMap(Audio.Playlists.Members.class));
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY, AudioColumns.ALBUM_KEY, AudioColumns.TITLE_KEY
                }, filter);
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_ALBUMART_ID:
                appendWhereStandalone(qb, "album_id=?", uri.getPathSegments().get(3));
                // fall-through
            case AUDIO_ALBUMART: {
                qb.setTables("album_art");

                final ArrayMap<String, String> projectionMap = new ArrayMap<>(
                        getProjectionMap(Audio.Thumbnails.class));
                projectionMap.put(Audio.Thumbnails._ID,
                        "album_id AS " + Audio.Thumbnails._ID);
                qb.setProjectionMap(projectionMap);

                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_ARTISTS_ID_ALBUMS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_artists_albums");
                    qb.setProjectionMap(getProjectionMap(Audio.Artists.Albums.class));

                    final String artistId = uri.getPathSegments().get(3);
                    appendWhereStandalone(qb, "artist_id=?", artistId);
                } else {
                    throw new UnsupportedOperationException("Albums cannot be directly modified");
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ALBUM_KEY
                }, filter);
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_ARTISTS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                // fall-through
            case AUDIO_ARTISTS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_artists");
                    qb.setProjectionMap(getProjectionMap(Audio.Artists.class));
                } else {
                    throw new UnsupportedOperationException("Artists cannot be directly modified");
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY
                }, filter);
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case AUDIO_ALBUMS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                // fall-through
            case AUDIO_ALBUMS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("audio_albums");
                    qb.setProjectionMap(getProjectionMap(Audio.Albums.class));
                } else {
                    throw new UnsupportedOperationException("Albums cannot be directly modified");
                }
                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY, AudioColumns.ALBUM_KEY
                }, filter);
                if (!allowGlobal && !checkCallingPermissionAudio(false, callingPackage)) {
                    // We don't have a great way to filter parsed metadata by
                    // owner, so callers need to hold READ_MEDIA_AUDIO
                    appendWhereStandalone(qb, "0");
                }
                break;
            }
            case VIDEO_MEDIA_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case VIDEO_MEDIA: {
                if (type == TYPE_QUERY) {
                    qb.setTables("video");
                    qb.setProjectionMap(
                            getProjectionMap(Video.Media.class));
                } else {
                    qb.setTables("files");
                    qb.setProjectionMap(
                            getProjectionMap(Video.Media.class, Files.FileColumns.class));
                    appendWhereStandalone(qb, FileColumns.MEDIA_TYPE + "=?",
                            FileColumns.MEDIA_TYPE_VIDEO);
                }
                if (!allowGlobal && !checkCallingPermissionVideo(forWrite, callingPackage)) {
                    appendWhereStandalone(qb, matchSharedPackagesClause);
                }
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case VIDEO_THUMBNAILS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(3));
                // fall-through
            case VIDEO_THUMBNAILS: {
                qb.setTables("videothumbnails");
                qb.setProjectionMap(getProjectionMap(Video.Thumbnails.class));
                if (!allowGlobal && !checkCallingPermissionVideo(forWrite, callingPackage)) {
                    appendWhereStandalone(qb,
                            "video_id IN (SELECT _id FROM video WHERE " +
                                    matchSharedPackagesClause + ")");
                }
                break;
            }
            case FILES_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(2));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case FILES: {
                qb.setTables("files");
                qb.setProjectionMap(getProjectionMap(Files.FileColumns.class));

                final ArrayList<String> options = new ArrayList<>();
                if (!allowGlobal && !allowLegacyRead) {
                    options.add(DatabaseUtils.bindSelection(matchSharedPackagesClause));
                    if (allowLegacy) {
                        options.add(DatabaseUtils.bindSelection("volume_name=?",
                                MediaStore.VOLUME_EXTERNAL_PRIMARY));
                    }
                    if (checkCallingPermissionAudio(forWrite, callingPackage)) {
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_AUDIO));
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_PLAYLIST));
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_SUBTITLE));
                        options.add(matchSharedPackagesClause
                                + " AND media_type=0 AND mime_type LIKE 'audio/%'");
                    }
                    if (checkCallingPermissionVideo(forWrite, callingPackage)) {
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_VIDEO));
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_SUBTITLE));
                        options.add(matchSharedPackagesClause
                                + " AND media_type=0 AND mime_type LIKE 'video/%'");
                    }
                    if (checkCallingPermissionImages(forWrite, callingPackage)) {
                        options.add(DatabaseUtils.bindSelection("media_type=?",
                                FileColumns.MEDIA_TYPE_IMAGE));
                        options.add(matchSharedPackagesClause
                                + " AND media_type=0 AND mime_type LIKE 'image/%'");
                    }
                    if (includedDefaultDirs != null) {
                        for (String defaultDir : includedDefaultDirs) {
                            options.add(FileColumns.RELATIVE_PATH + " LIKE '" + defaultDir + "/%'");
                        }
                    }
                }
                if (options.size() > 0) {
                    appendWhereStandalone(qb, TextUtils.join(" OR ", options));
                }

                appendWhereStandaloneFilter(qb, new String[] {
                        AudioColumns.ARTIST_KEY, AudioColumns.ALBUM_KEY, AudioColumns.TITLE_KEY
                }, filter);
                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            case DOWNLOADS_ID:
                appendWhereStandalone(qb, "_id=?", uri.getPathSegments().get(2));
                matchPending = MATCH_INCLUDE;
                matchTrashed = MATCH_INCLUDE;
                // fall-through
            case DOWNLOADS: {
                if (type == TYPE_QUERY) {
                    qb.setTables("downloads");
                    qb.setProjectionMap(
                            getProjectionMap(Downloads.class));
                } else {
                    qb.setTables("files");
                    qb.setProjectionMap(
                            getProjectionMap(Downloads.class, Files.FileColumns.class));
                    appendWhereStandalone(qb, FileColumns.IS_DOWNLOAD + "=1");
                }

                final ArrayList<String> options = new ArrayList<>();
                if (!allowGlobal && !allowLegacyRead) {
                    options.add(DatabaseUtils.bindSelection(matchSharedPackagesClause));
                    if (allowLegacy) {
                        options.add(DatabaseUtils.bindSelection("volume_name=?",
                                MediaStore.VOLUME_EXTERNAL_PRIMARY));
                    }
                }
                if (options.size() > 0) {
                    appendWhereStandalone(qb, TextUtils.join(" OR ", options));
                }

                appendWhereStandaloneMatch(qb, FileColumns.IS_PENDING, matchPending, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_TRASHED, matchTrashed, uri);
                appendWhereStandaloneMatch(qb, FileColumns.IS_FAVORITE, matchFavorite, uri);
                if (honored != null) {
                    honored.accept(QUERY_ARG_MATCH_PENDING);
                    honored.accept(QUERY_ARG_MATCH_TRASHED);
                    honored.accept(QUERY_ARG_MATCH_FAVORITE);
                }
                if (!includeAllVolumes) {
                    appendWhereStandalone(qb, FileColumns.VOLUME_NAME + " IN " + includeVolumes);
                }
                break;
            }
            default:
                throw new UnsupportedOperationException(
                        "Unknown or unsupported URL: " + uri.toString());
        }

        // To ensure we're enforcing our security model, all operations must
        // have a projection map configured
        if (qb.getProjectionMap() == null) {
            throw new IllegalStateException("All queries must have a projection map");
        }

        // If caller is an older app, we're willing to let through a
        // greylist of technically invalid columns
        if (getCallingPackageTargetSdkVersion() < Build.VERSION_CODES.Q) {
            qb.setProjectionGreylist(sGreylist);
        }

        return qb;
    }

    /**
     * @return {@code true} if app requests to include database rows from
     * recently unmounted volume.
     * {@code false} otherwise.
     */
    private boolean shouldIncludeRecentlyUnmountedVolumes(Uri uri, Bundle extras) {
        if (isFuseThread()) {
            // File path requests don't require to query from unmounted volumes.
            return false;
        }

        boolean isIncludeVolumesChangeEnabled = SdkLevel.isAtLeastS() &&
                CompatChanges.isChangeEnabled(ENABLE_INCLUDE_ALL_VOLUMES, Binder.getCallingUid());
        if ("1".equals(uri.getQueryParameter(ALL_VOLUMES))) {
            // Support uri parameter only in R OS and below. Apps should use
            // MediaStore#QUERY_ARG_RECENTLY_UNMOUNTED_VOLUMES on S OS onwards.
            if (!isIncludeVolumesChangeEnabled) {
                return true;
            }
            throw new IllegalArgumentException("Unsupported uri parameter \"all_volumes\"");
        }
        if (isIncludeVolumesChangeEnabled) {
            // MediaStore#QUERY_ARG_INCLUDE_RECENTLY_UNMOUNTED_VOLUMES is only supported on S OS and
            // for app targeting targetSdk>=S.
            return extras.getBoolean(MediaStore.QUERY_ARG_INCLUDE_RECENTLY_UNMOUNTED_VOLUMES,
                    false);
        }
        return false;
    }

    /**
     * Determine if given {@link Uri} has a
     * {@link MediaColumns#OWNER_PACKAGE_NAME} column.
     */
    private boolean hasOwnerPackageName(Uri uri) {
        // It's easier to maintain this as an inverted list
        final int table = matchUri(uri, true);
        switch (table) {
            case IMAGES_THUMBNAILS_ID:
            case IMAGES_THUMBNAILS:
            case VIDEO_THUMBNAILS_ID:
            case VIDEO_THUMBNAILS:
            case AUDIO_ALBUMART:
            case AUDIO_ALBUMART_ID:
            case AUDIO_ALBUMART_FILE_ID:
                return false;
            default:
                return true;
        }
    }

    /**
     * @deprecated all operations should be routed through the overload that
     *             accepts a {@link Bundle} of extras.
     */
    @Override
    @Deprecated
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return delete(uri,
                DatabaseUtils.createSqlQueryBundle(selection, selectionArgs, null));
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable Bundle extras) {
        Trace.beginSection("delete");
        try {
            return deleteInternal(uri, extras);
        } catch (FallbackException e) {
            return e.translateForUpdateDelete(getCallingPackageTargetSdkVersion());
        } finally {
            Trace.endSection();
        }
    }

    private int deleteInternal(@NonNull Uri uri, @Nullable Bundle extras)
            throws FallbackException {
        final String volumeName = getVolumeName(uri);
        PulledMetrics.logVolumeAccessViaMediaProvider(getCallingUidOrSelf(), volumeName);

        extras = (extras != null) ? extras : new Bundle();
        // REDACTED_URI_BUNDLE_KEY extra should only be set inside MediaProvider.
        extras.remove(QUERY_ARG_REDACTED_URI);

        if (isRedactedUri(uri)) {
            // we don't support deletion on redacted uris.
            return 0;
        }

        // INCLUDED_DEFAULT_DIRECTORIES extra should only be set inside MediaProvider.
        extras.remove(INCLUDED_DEFAULT_DIRECTORIES);

        uri = safeUncanonicalize(uri);
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        switch (match) {
            case AUDIO_MEDIA_ID:
            case AUDIO_PLAYLISTS_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
            case DOWNLOADS_ID:
            case FILES_ID: {
                if (!isFuseThread() && getCachedCallingIdentityForFuse(Binder.getCallingUid()).
                        removeDeletedRowId(Long.parseLong(uri.getLastPathSegment()))) {
                    // Apps sometimes delete the file via filePath and then try to delete the db row
                    // using MediaProvider#delete. Since we would have already deleted the db row
                    // during the filePath operation, the latter will result in a security
                    // exception. Apps which don't expect an exception will break here. Since we
                    // have already deleted the db row, silently return zero as deleted count.
                    return 0;
                }
            }
            break;
            default:
                // For other match types, given uri will not correspond to a valid file.
                break;
        }

        final String userWhere = extras.getString(QUERY_ARG_SQL_SELECTION);
        final String[] userWhereArgs = extras.getStringArray(QUERY_ARG_SQL_SELECTION_ARGS);

        int count = 0;

        final int targetSdkVersion = getCallingPackageTargetSdkVersion();

        // handle MEDIA_SCANNER before calling getDatabaseForUri()
        if (match == MEDIA_SCANNER) {
            if (mMediaScannerVolume == null) {
                return 0;
            }

            final DatabaseHelper helper = getDatabaseForUri(
                    MediaStore.Files.getContentUri(mMediaScannerVolume));

            helper.mScanStopTime = SystemClock.elapsedRealtime();

            mMediaScannerVolume = null;
            return 1;
        }

        if (match == VOLUMES_ID) {
            detachVolume(uri);
            count = 1;
        }

        final DatabaseHelper helper = getDatabaseForUri(uri);
        switch (match) {
            case AUDIO_PLAYLISTS_ID_MEMBERS_ID:
                extras.putString(QUERY_ARG_SQL_SELECTION,
                        BaseColumns._ID + "=" + uri.getPathSegments().get(5));
                // fall-through
            case AUDIO_PLAYLISTS_ID_MEMBERS: {
                final long playlistId = Long.parseLong(uri.getPathSegments().get(3));
                final Uri playlistUri = ContentUris.withAppendedId(
                        MediaStore.Audio.Playlists.getContentUri(volumeName), playlistId);

                // Playlist contents are always persisted directly into playlist
                // files on disk to ensure that we can reliably migrate between
                // devices and recover from database corruption
                int numOfRemovedPlaylistMembers = removePlaylistMembers(playlistUri, extras);
                if (numOfRemovedPlaylistMembers > 0) {
                    acceptWithExpansion(helper::notifyDelete, volumeName, playlistId,
                            FileColumns.MEDIA_TYPE_PLAYLIST, false);
                }
                return numOfRemovedPlaylistMembers;
            }
        }

        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_DELETE, match, uri, extras, null);

        {
            // Give callers interacting with a specific media item a chance to
            // escalate access if they don't already have it
            switch (match) {
                case AUDIO_MEDIA_ID:
                case VIDEO_MEDIA_ID:
                case IMAGES_MEDIA_ID:
                    enforceCallingPermission(uri, extras, true);
            }

            final String[] projection = new String[] {
                    FileColumns.MEDIA_TYPE,
                    FileColumns.DATA,
                    FileColumns._ID,
                    FileColumns.IS_DOWNLOAD,
                    FileColumns.MIME_TYPE,
            };
            final boolean isFilesTable = qb.getTables().equals("files");
            final LongSparseArray<String> deletedDownloadIds = new LongSparseArray<>();
            final int[] countPerMediaType = new int[FileColumns.MEDIA_TYPE_COUNT];
            if (isFilesTable) {
                String deleteparam = uri.getQueryParameter(MediaStore.PARAM_DELETE_DATA);
                if (deleteparam == null || ! deleteparam.equals("false")) {
                    Cursor c = qb.query(helper, projection, userWhere, userWhereArgs,
                            null, null, null, null, null);
                    try {
                        while (c.moveToNext()) {
                            final int mediaType = c.getInt(0);
                            final String data = c.getString(1);
                            final long id = c.getLong(2);
                            final int isDownload = c.getInt(3);
                            final String mimeType = c.getString(4);

                            // TODO(b/188782594) Consider logging mime type access on delete too.

                            // Forget that caller is owner of this item
                            mCallingIdentity.get().setOwned(id, false);

                            deleteIfAllowed(uri, extras, data);
                            int res = qb.delete(helper, BaseColumns._ID + "=" + id, null);
                            count += res;
                            // Avoid ArrayIndexOutOfBounds if more mediaTypes are added,
                            // but mediaTypeSize is not updated
                            if (res > 0 && mediaType < countPerMediaType.length) {
                                countPerMediaType[mediaType] += res;
                            }

                            if (isDownload == 1) {
                                deletedDownloadIds.put(id, mimeType);
                            }
                        }
                    } finally {
                        FileUtils.closeQuietly(c);
                    }
                    // Do not allow deletion if the file/object is referenced as parent
                    // by some other entries. It could cause database corruption.
                    appendWhereStandalone(qb, ID_NOT_PARENT_CLAUSE);
                }
            }

            switch (match) {
                case AUDIO_GENRES_ID_MEMBERS:
                    throw new FallbackException("Genres are read-only", Build.VERSION_CODES.R);

                case IMAGES_THUMBNAILS_ID:
                case IMAGES_THUMBNAILS:
                case VIDEO_THUMBNAILS_ID:
                case VIDEO_THUMBNAILS:
                    // Delete the referenced files first.
                    Cursor c = qb.query(helper, sDataOnlyColumn, userWhere, userWhereArgs, null,
                            null, null, null, null);
                    if (c != null) {
                        try {
                            while (c.moveToNext()) {
                                deleteIfAllowed(uri, extras, c.getString(0));
                            }
                        } finally {
                            FileUtils.closeQuietly(c);
                        }
                    }
                    count += deleteRecursive(qb, helper, userWhere, userWhereArgs);
                    break;

                default:
                    count += deleteRecursive(qb, helper, userWhere, userWhereArgs);
                    break;
            }

            if (deletedDownloadIds.size() > 0) {
                notifyDownloadManagerOnDelete(helper, deletedDownloadIds);
            }

            // Check for other URI format grants for File API call only. Check right before
            // returning count = 0, to leave positive cases performance unaffected.
            if (count == 0 && isFuseThread()) {
                count += deleteWithOtherUriGrants(uri, helper, projection, userWhere, userWhereArgs,
                        extras);
            }

            if (isFilesTable && !isCallingPackageSelf()) {
                Metrics.logDeletion(volumeName, mCallingIdentity.get().uid,
                        getCallingPackageOrSelf(), count, countPerMediaType);
            }
        }

        return count;
    }

    private int deleteWithOtherUriGrants(@NonNull Uri uri, DatabaseHelper helper,
            String[] projection, String userWhere, String[] userWhereArgs,
            @Nullable Bundle extras) {
        try (Cursor c = queryForSingleItemAsMediaProvider(uri, projection, userWhere, userWhereArgs,
                    null)) {
            final int mediaType = c.getInt(0);
            final String data = c.getString(1);
            final long id = c.getLong(2);
            final int isDownload = c.getInt(3);
            final String mimeType = c.getString(4);

            final Uri uriGranted = getOtherUriGrantsForPath(data, mediaType, Long.toString(id),
                    /* forWrite */ true);
            if (uriGranted != null) {
                // 1. delete file
                deleteIfAllowed(uriGranted, extras, data);
                // 2. delete file row from the db
                final boolean allowHidden = isCallingPackageAllowedHidden();
                final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_DELETE,
                        matchUri(uriGranted, allowHidden), uriGranted, extras, null);
                int count = qb.delete(helper, BaseColumns._ID + "=" + id, null);

                if (isDownload == 1) {
                    final LongSparseArray<String> deletedDownloadIds = new LongSparseArray<>();
                    deletedDownloadIds.put(id, mimeType);
                    notifyDownloadManagerOnDelete(helper, deletedDownloadIds);
                }
                return count;
            }
        } catch (FileNotFoundException ignored) {
            // Do nothing. Returns 0 files deleted.
        }
        return 0;
    }

    private void notifyDownloadManagerOnDelete(DatabaseHelper helper,
            LongSparseArray<String> deletedDownloadIds) {
        // Do this on a background thread, since we don't want to make binder
        // calls as part of a FUSE call.
        helper.postBackground(() -> {
            DownloadManager dm = getContext().getSystemService(DownloadManager.class);
            if (dm != null) {
                dm.onMediaStoreDownloadsDeleted(deletedDownloadIds);
            }
        });
    }

    /**
     * Executes identical delete repeatedly within a single transaction until
     * stability is reached. Combined with {@link #ID_NOT_PARENT_CLAUSE}, this
     * can be used to recursively delete all matching entries, since it only
     * deletes parents when no references remaining.
     */
    private int deleteRecursive(SQLiteQueryBuilder qb, DatabaseHelper helper, String userWhere,
            String[] userWhereArgs) {
        return (int) helper.runWithTransaction((db) -> {
            synchronized (mDirectoryCache) {
                mDirectoryCache.clear();
            }

            int n = 0;
            int total = 0;
            do {
                n = qb.delete(helper, userWhere, userWhereArgs);
                total += n;
            } while (n > 0);
            return total;
        });
    }

    @Nullable
    @VisibleForTesting
    Uri getRedactedUri(@NonNull Uri uri) {
        if (!isUriSupportedForRedaction(uri)) {
            return null;
        }

        DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(uri);
        } catch (VolumeNotFoundException e) {
            throw e.rethrowAsIllegalArgumentException();
        }

        try (final Cursor c = helper.runWithoutTransaction(
                (db) -> db.query("files",
                        new String[]{FileColumns.REDACTED_URI_ID}, FileColumns._ID + "=?",
                        new String[]{uri.getLastPathSegment()}, null, null, null))) {
            // Database entry for uri not found.
            if (!c.moveToFirst()) return null;

            String redactedUriID = c.getString(c.getColumnIndex(FileColumns.REDACTED_URI_ID));
            if (redactedUriID == null) {
                // No redacted has even been created for this uri. Create a new redacted URI ID for
                // the uri and store it in the DB.
                redactedUriID = REDACTED_URI_ID_PREFIX + UUID.randomUUID().toString().replace("-",
                        "");

                ContentValues cv = new ContentValues();
                cv.put(FileColumns.REDACTED_URI_ID, redactedUriID);
                int rowsAffected = helper.runWithTransaction(
                        (db) -> db.update("files", cv, FileColumns._ID + "=?",
                                new String[]{uri.getLastPathSegment()}));
                if (rowsAffected == 0) {
                    // this shouldn't happen ideally, only reason this might happen is if the db
                    // entry got deleted in b/w in which case we should return null.
                    return null;
                }
            }

            // Create and return a uri with ID = redactedUriID.
            final Uri.Builder builder = ContentUris.removeId(uri).buildUpon();
            builder.appendPath(redactedUriID);

            return builder.build();
        }
    }

    @NonNull
    @VisibleForTesting
    List<Uri> getRedactedUri(@NonNull List<Uri> uris) {
        ArrayList<Uri> redactedUris = new ArrayList<>();
        for (Uri uri : uris) {
            redactedUris.add(getRedactedUri(uri));
        }

        return redactedUris;
    }

    @Override
    public Bundle call(String method, String arg, Bundle extras) {
        Trace.beginSection("call");
        try {
            return callInternal(method, arg, extras);
        } finally {
            Trace.endSection();
        }
    }

    private Bundle callInternal(String method, String arg, Bundle extras) {
        switch (method) {
            case MediaStore.RESOLVE_PLAYLIST_MEMBERS_CALL: {
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                final CallingIdentity providerToken = clearCallingIdentity();
                try {
                    final Uri playlistUri = extras.getParcelable(MediaStore.EXTRA_URI);
                    resolvePlaylistMembers(playlistUri);
                } finally {
                    restoreCallingIdentity(providerToken);
                    restoreLocalCallingIdentity(token);
                }
                return null;
            }
            case MediaStore.RUN_IDLE_MAINTENANCE_CALL: {
                // Protect ourselves from random apps by requiring a generic
                // permission held by common debugging components, such as shell
                getContext().enforceCallingOrSelfPermission(
                        android.Manifest.permission.DUMP, TAG);
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                final CallingIdentity providerToken = clearCallingIdentity();
                try {
                    onIdleMaintenance(new CancellationSignal());
                } finally {
                    restoreCallingIdentity(providerToken);
                    restoreLocalCallingIdentity(token);
                }
                return null;
            }
            case MediaStore.WAIT_FOR_IDLE_CALL: {
                // TODO(b/195009139): Remove after overriding wait for idle in test to sync picker
                // Syncing the picker while waiting for idle fixes tests with the picker db
                // flag enabled because the picker db is in a consistent state with the external
                // db after the sync
                syncAllMedia();
                ForegroundThread.waitForIdle();
                final CountDownLatch latch = new CountDownLatch(1);
                BackgroundThread.getExecutor().execute(() -> {
                    latch.countDown();
                });
                try {
                    latch.await(30, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    throw new IllegalStateException(e);
                }
                return null;
            }
            case MediaStore.SCAN_FILE_CALL:
            case MediaStore.SCAN_VOLUME_CALL: {
                final int userId = uidToUserId(Binder.getCallingUid());
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                final CallingIdentity providerToken = clearCallingIdentity();
                try {
                    final Bundle res = new Bundle();
                    switch (method) {
                        case MediaStore.SCAN_FILE_CALL: {
                            final File file = new File(arg);
                            res.putParcelable(Intent.EXTRA_STREAM, scanFile(file, REASON_DEMAND));
                            break;
                        }
                        case MediaStore.SCAN_VOLUME_CALL: {
                            final String volumeName = arg;
                            try {
                                MediaVolume volume = mVolumeCache.findVolume(volumeName,
                                        UserHandle.of(userId));
                                MediaService.onScanVolume(getContext(), volume, REASON_DEMAND);
                            } catch (FileNotFoundException e) {
                                Log.w(TAG, "Failed to find volume " + volumeName, e);
                            }
                            break;
                        }
                    }
                    return res;
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    restoreCallingIdentity(providerToken);
                    restoreLocalCallingIdentity(token);
                }
            }
            case MediaStore.GET_VERSION_CALL: {
                final String volumeName = extras.getString(Intent.EXTRA_TEXT);

                final DatabaseHelper helper;
                try {
                    helper = getDatabaseForUri(MediaStore.Files.getContentUri(volumeName));
                } catch (VolumeNotFoundException e) {
                    throw e.rethrowAsIllegalArgumentException();
                }

                final String version = helper.runWithoutTransaction((db) -> {
                    return db.getVersion() + ":" + DatabaseHelper.getOrCreateUuid(db);
                });

                final Bundle res = new Bundle();
                res.putString(Intent.EXTRA_TEXT, version);
                return res;
            }
            case MediaStore.GET_GENERATION_CALL: {
                final String volumeName = extras.getString(Intent.EXTRA_TEXT);

                final DatabaseHelper helper;
                try {
                    helper = getDatabaseForUri(MediaStore.Files.getContentUri(volumeName));
                } catch (VolumeNotFoundException e) {
                    throw e.rethrowAsIllegalArgumentException();
                }

                final long generation = helper.runWithoutTransaction((db) -> {
                    return DatabaseHelper.getGeneration(db);
                });

                final Bundle res = new Bundle();
                res.putLong(Intent.EXTRA_INDEX, generation);
                return res;
            }
            case MediaStore.GET_DOCUMENT_URI_CALL: {
                final Uri mediaUri = extras.getParcelable(MediaStore.EXTRA_URI);
                enforceCallingPermission(mediaUri, extras, false);

                final Uri fileUri;
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                try {
                    fileUri = Uri.fromFile(queryForDataFile(mediaUri, null));
                } catch (FileNotFoundException e) {
                    throw new IllegalArgumentException(e);
                } finally {
                    restoreLocalCallingIdentity(token);
                }

                try (ContentProviderClient client = getContext().getContentResolver()
                        .acquireUnstableContentProviderClient(
                                getExternalStorageProviderAuthority())) {
                    extras.putParcelable(MediaStore.EXTRA_URI, fileUri);
                    return client.call(method, null, extras);
                } catch (RemoteException e) {
                    throw new IllegalStateException(e);
                }
            }
            case MediaStore.GET_MEDIA_URI_CALL: {
                final Uri documentUri = extras.getParcelable(MediaStore.EXTRA_URI);
                getContext().enforceCallingUriPermission(documentUri,
                        Intent.FLAG_GRANT_READ_URI_PERMISSION, TAG);

                final int callingPid = mCallingIdentity.get().pid;
                final int callingUid = mCallingIdentity.get().uid;
                final String callingPackage = getCallingPackage();
                final CallingIdentity token = clearCallingIdentity();
                final String authority = documentUri.getAuthority();

                if (!authority.equals(MediaDocumentsProvider.AUTHORITY) &&
                        !authority.equals(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY)) {
                    throw new IllegalArgumentException("Provider for this Uri is not supported.");
                }

                try (ContentProviderClient client = getContext().getContentResolver()
                        .acquireUnstableContentProviderClient(authority)) {
                    final Bundle clientRes = client.call(method, null, extras);
                    final Uri fileUri = clientRes.getParcelable(MediaStore.EXTRA_URI);
                    final Bundle res = new Bundle();
                    final Uri mediaStoreUri = fileUri.getAuthority().equals(MediaStore.AUTHORITY) ?
                            fileUri : queryForMediaUri(new File(fileUri.getPath()), null);
                    copyUriPermissionGrants(documentUri, mediaStoreUri, callingPid,
                            callingUid, callingPackage);
                    res.putParcelable(MediaStore.EXTRA_URI, mediaStoreUri);
                    return res;
                } catch (FileNotFoundException e) {
                    throw new IllegalArgumentException(e);
                } catch (RemoteException e) {
                    throw new IllegalStateException(e);
                } finally {
                    restoreCallingIdentity(token);
                }
            }
            case MediaStore.GET_REDACTED_MEDIA_URI_CALL: {
                final Uri uri = extras.getParcelable(MediaStore.EXTRA_URI);
                // NOTE: It is ok to update the DB and return a redacted URI for the cases when
                // the user code only has read access, hence we don't check for write permission.
                enforceCallingPermission(uri, Bundle.EMPTY, false);
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                try {
                    final Bundle res = new Bundle();
                    res.putParcelable(MediaStore.EXTRA_URI, getRedactedUri(uri));
                    return res;
                } finally {
                    restoreLocalCallingIdentity(token);
                }
            }
            case MediaStore.GET_REDACTED_MEDIA_URI_LIST_CALL: {
                final List<Uri> uris = extras.getParcelableArrayList(MediaStore.EXTRA_URI_LIST);
                // NOTE: It is ok to update the DB and return a redacted URI for the cases when
                // the user code only has read access, hence we don't check for write permission.
                enforceCallingPermission(uris, false);
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                try {
                    final Bundle res = new Bundle();
                    res.putParcelableArrayList(MediaStore.EXTRA_URI_LIST,
                            (ArrayList<? extends Parcelable>) getRedactedUri(uris));
                    return res;
                } finally {
                    restoreLocalCallingIdentity(token);
                }
            }
            case MediaStore.CREATE_WRITE_REQUEST_CALL:
            case MediaStore.CREATE_FAVORITE_REQUEST_CALL:
            case MediaStore.CREATE_TRASH_REQUEST_CALL:
            case MediaStore.CREATE_DELETE_REQUEST_CALL: {
                final PendingIntent pi = createRequest(method, extras);
                final Bundle res = new Bundle();
                res.putParcelable(MediaStore.EXTRA_RESULT, pi);
                return res;
            }
            case MediaStore.IS_SYSTEM_GALLERY_CALL:
                final LocalCallingIdentity token = clearLocalCallingIdentity();
                try {
                    String packageName = arg;
                    int uid = extras.getInt(MediaStore.EXTRA_IS_SYSTEM_GALLERY_UID);
                    boolean isSystemGallery = PermissionUtils.checkWriteImagesOrVideoAppOps(
                            getContext(), uid, packageName, getContext().getAttributionTag());
                    Bundle res = new Bundle();
                    res.putBoolean(MediaStore.EXTRA_IS_SYSTEM_GALLERY_RESPONSE, isSystemGallery);
                    return res;
                } finally {
                    restoreLocalCallingIdentity(token);
                }
            case MediaStore.SET_CLOUD_PROVIDER_CALL: {
                // TODO(b/190713331): Remove after initial development
                final String cloudProvider = extras.getString(MediaStore.EXTRA_CLOUD_PROVIDER);
                Log.i(TAG, "Test initiated cloud provider switch: " + cloudProvider);
                mPickerSyncController.forceSetCloudProvider(cloudProvider);
                // fall-through
            }
            case MediaStore.SYNC_PROVIDERS_CALL: {
                syncAllMedia();
                return new Bundle();
            }
            case MediaStore.IS_SUPPORTED_CLOUD_PROVIDER_CALL: {
                final boolean isSupported = mPickerSyncController.isProviderSupported(arg,
                        Binder.getCallingUid());

                Bundle bundle = new Bundle();
                bundle.putBoolean(MediaStore.EXTRA_CLOUD_PROVIDER_RESULT, isSupported);
                return bundle;
            }
            case MediaStore.IS_CURRENT_CLOUD_PROVIDER_CALL: {
                final boolean isEnabled = mPickerSyncController.isProviderEnabled(arg,
                        Binder.getCallingUid());

                Bundle bundle = new Bundle();
                bundle.putBoolean(MediaStore.EXTRA_CLOUD_PROVIDER_RESULT, isEnabled);
                return bundle;
            }
            case MediaStore.NOTIFY_CLOUD_MEDIA_CHANGED_EVENT_CALL: {
                final boolean notifyCloudEventResult;
                if (mPickerSyncController.isProviderEnabled(arg, Binder.getCallingUid())) {
                    mPickerSyncController.notifyMediaEvent();
                    notifyCloudEventResult = true;
                } else {
                    notifyCloudEventResult = false;
                }

                Bundle bundle = new Bundle();
                bundle.putBoolean(MediaStore.EXTRA_CLOUD_PROVIDER_RESULT,
                        notifyCloudEventResult);
                return bundle;
            }
            case MediaStore.USES_FUSE_PASSTHROUGH: {
                boolean isEnabled = false;
                try {
                    FuseDaemon daemon = getFuseDaemonForFile(new File(arg));
                    if (daemon != null) {
                        isEnabled = daemon.usesFusePassthrough();
                    }
                } catch (FileNotFoundException e) {
                }

                Bundle bundle = new Bundle();
                bundle.putBoolean(MediaStore.USES_FUSE_PASSTHROUGH_RESULT, isEnabled);
                return bundle;
            }
            default:
                throw new UnsupportedOperationException("Unsupported call: " + method);
        }
    }

    private void syncAllMedia() {
        // Clear the binder calling identity so that we can sync the unexported
        // local_provider while running as MediaProvider
        final long t = Binder.clearCallingIdentity();
        try {
            Log.v(TAG, "Test initiated cloud provider sync");
            mPickerSyncController.syncAllMedia();
        } finally {
            Binder.restoreCallingIdentity(t);
        }
    }

    private AssetFileDescriptor getOriginalMediaFormatFileDescriptor(Bundle extras)
            throws FileNotFoundException {
        try (ParcelFileDescriptor inputPfd =
                extras.getParcelable(MediaStore.EXTRA_FILE_DESCRIPTOR)) {
            File file = getFileFromFileDescriptor(inputPfd);
            // Convert from FUSE file to lower fs file because the supportsTranscode() check below
            // expects a lower fs file format
            file = fromFuseFile(file);
            if (!mTranscodeHelper.supportsTranscode(file.getPath())) {
                // Note that we should be checking if a file is a modern format and not just
                // that it supports transcoding, unfortunately, checking modern format
                // requires either a db query or media scan which can lead to ANRs if apps
                // or the system implicitly call this method as part of a
                // MediaPlayer#setDataSource.
                throw new FileNotFoundException("Input file descriptor is already original");
            }

            FuseDaemon fuseDaemon = getFuseDaemonForFile(file);
            int uid = Binder.getCallingUid();

            FdAccessResult result = fuseDaemon.checkFdAccess(inputPfd, uid);
            if (!result.isSuccess()) {
                throw new FileNotFoundException("Invalid path for original media format file");
            }

            String outputPath = result.filePath;
            boolean shouldRedact = result.shouldRedact;

            int posixMode = Os.fcntlInt(inputPfd.getFileDescriptor(), F_GETFL,
                    0 /* args */);
            int modeBits = FileUtils.translateModePosixToPfd(posixMode);

            ParcelFileDescriptor pfd = openWithFuse(outputPath, uid, 0 /* mediaCapabilitiesUid */,
                    modeBits, shouldRedact, false /* shouldTranscode */,
                    0 /* transcodeReason */);
            return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
        } catch (IOException e) {
            throw new FileNotFoundException("Failed to fetch original file descriptor");
        } catch (ErrnoException e) {
            Log.w(TAG, "Failed to fetch access mode for file descriptor", e);
            throw new FileNotFoundException("Failed to fetch access mode for file descriptor");
        }
    }

    /**
     * Grant similar read/write access for mediaStoreUri as the caller has for documentsUri.
     *
     * Note: This function assumes that read permission check for documentsUri is already enforced.
     * Note: This function currently does not check/grant for persisted Uris. Support for this can
     * be added eventually, but the calling application will have to call
     * ContentResolver#takePersistableUriPermission(Uri, int) for the mediaStoreUri to persist.
     *
     * @param documentsUri DocumentsProvider format content Uri
     * @param mediaStoreUri MediaStore format content Uri
     * @param callingPid pid of the caller
     * @param callingUid uid of the caller
     * @param callingPackage package name of the caller
     */
    private void copyUriPermissionGrants(Uri documentsUri, Uri mediaStoreUri,
            int callingPid, int callingUid, String callingPackage) {
        // No need to check for read permission, as we enforce it already.
        int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
        if (getContext().checkUriPermission(documentsUri, callingPid, callingUid,
                Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == PERMISSION_GRANTED) {
            modeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
        }
        getContext().grantUriPermission(callingPackage, mediaStoreUri, modeFlags);
    }

    static List<Uri> collectUris(ClipData clipData) {
        final ArrayList<Uri> res = new ArrayList<>();
        for (int i = 0; i < clipData.getItemCount(); i++) {
            res.add(clipData.getItemAt(i).getUri());
        }
        return res;
    }

    /**
     * Return the filesystem path of the real file on disk that is represented
     * by the given {@link ParcelFileDescriptor}.
     *
     * Note that the file may be a FUSE or lower fs file and depending on the purpose might need
     * to be converted with {@link FileUtils#toFuseFile} or {@link FileUtils#fromFuseFile}.
     *
     * Copied from {@link ParcelFileDescriptor#getFile}
     */
    private static File getFileFromFileDescriptor(ParcelFileDescriptor fileDescriptor)
            throws IOException {
        try {
            final String path = Os.readlink("/proc/self/fd/" + fileDescriptor.getFd());
            if (OsConstants.S_ISREG(Os.stat(path).st_mode)) {
                return new File(path);
            } else {
                throw new IOException("Not a regular file: " + path);
            }
        } catch (ErrnoException e) {
            throw e.rethrowAsIOException();
        }
    }

    /**
     * Generate the {@link PendingIntent} for the given grant request. This
     * method also checks the incoming arguments for security purposes
     * before creating the privileged {@link PendingIntent}.
     */
    private @NonNull PendingIntent createRequest(@NonNull String method, @NonNull Bundle extras) {
        final ClipData clipData = extras.getParcelable(MediaStore.EXTRA_CLIP_DATA);
        final List<Uri> uris = collectUris(clipData);

        for (Uri uri : uris) {
            final int match = matchUri(uri, false);
            switch (match) {
                case IMAGES_MEDIA_ID:
                case AUDIO_MEDIA_ID:
                case VIDEO_MEDIA_ID:
                case AUDIO_PLAYLISTS_ID:
                    // Caller is requesting a specific media item by its ID,
                    // which means it's valid for requests
                    break;
                case FILES_ID:
                    // Allow only subtitle files
                    if (!isSubtitleFile(uri)) {
                        throw new IllegalArgumentException(
                                "All requested items must be Media items");
                    }
                    break;
                default:
                    throw new IllegalArgumentException(
                            "All requested items must be referenced by specific ID");
            }
        }

        // Enforce that limited set of columns can be mutated
        final ContentValues values = extras.getParcelable(MediaStore.EXTRA_CONTENT_VALUES);
        final List<String> allowedColumns;
        switch (method) {
            case MediaStore.CREATE_FAVORITE_REQUEST_CALL:
                allowedColumns = Arrays.asList(
                        MediaColumns.IS_FAVORITE);
                break;
            case MediaStore.CREATE_TRASH_REQUEST_CALL:
                allowedColumns = Arrays.asList(
                        MediaColumns.IS_TRASHED);
                break;
            default:
                allowedColumns = Arrays.asList();
                break;
        }
        if (values != null) {
            for (String key : values.keySet()) {
                if (!allowedColumns.contains(key)) {
                    throw new IllegalArgumentException("Invalid column " + key);
                }
            }
        }

        final Context context = getContext();
        final Intent intent = new Intent(method, null, context, PermissionActivity.class);
        intent.putExtras(extras);
        return PendingIntent.getActivity(context, PermissionActivity.REQUEST_CODE, intent,
                FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE);
    }

    /**
     * @return true if the given Files uri has media_type=MEDIA_TYPE_SUBTITLE
     */
    private boolean isSubtitleFile(Uri uri) {
        final LocalCallingIdentity tokenInner = clearLocalCallingIdentity();
        try (Cursor cursor = queryForSingleItem(uri, new String[]{FileColumns.MEDIA_TYPE}, null,
                null, null)) {
            return cursor.getInt(0) == FileColumns.MEDIA_TYPE_SUBTITLE;
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find database row for requested uri " + uri, e);
        } finally {
            restoreLocalCallingIdentity(tokenInner);
        }
        return false;
    }

    /**
     * Ensure that all local databases have a custom collator registered for the
     * given {@link ULocale} locale.
     *
     * @return the corresponding custom collation name to be used in
     *         {@code ORDER BY} clauses.
     */
    private @NonNull String ensureCustomCollator(@NonNull String locale) {
        // Quick check that requested locale looks reasonable
        new ULocale(locale);

        final String collationName = "custom_" + locale.replaceAll("[^a-zA-Z]", "");
        synchronized (mCustomCollators) {
            if (!mCustomCollators.contains(collationName)) {
                for (DatabaseHelper helper : new DatabaseHelper[] {
                        mInternalDatabase,
                        mExternalDatabase
                }) {
                    helper.runWithoutTransaction((db) -> {
                        db.execPerConnectionSQL("SELECT icu_load_collation(?, ?);",
                                new String[] { locale, collationName });
                        return null;
                    });
                }
                mCustomCollators.add(collationName);
            }
        }
        return collationName;
    }

    private int pruneThumbnails(@NonNull SQLiteDatabase db, @NonNull CancellationSignal signal) {
        int prunedCount = 0;

        // Determine all known media items
        final LongArray knownIds = new LongArray();
        try (Cursor c = db.query(true, "files", new String[] { BaseColumns._ID },
                null, null, null, null, null, null, signal)) {
            while (c.moveToNext()) {
                knownIds.add(c.getLong(0));
            }
        }

        final long[] knownIdsRaw = knownIds.toArray();
        Arrays.sort(knownIdsRaw);

        for (MediaVolume volume : mVolumeCache.getExternalVolumes()) {
            final List<File> thumbDirs;
            try {
                thumbDirs = getThumbnailDirectories(volume);
            } catch (FileNotFoundException e) {
                Log.w(TAG, "Failed to resolve volume " + volume.getName(), e);
                continue;
            }

            // Reconcile all thumbnails, deleting stale items
            for (File thumbDir : thumbDirs) {
                // Possibly bail before digging into each directory
                signal.throwIfCanceled();

                final File[] files = thumbDir.listFiles();
                for (File thumbFile : (files != null) ? files : new File[0]) {
                    if (Objects.equals(thumbFile.getName(), FILE_DATABASE_UUID)) continue;
                    final String name = FileUtils.extractFileName(thumbFile.getName());
                    try {
                        final long id = Long.parseLong(name);
                        if (Arrays.binarySearch(knownIdsRaw, id) >= 0) {
                            // Thumbnail belongs to known media, keep it
                            continue;
                        }
                    } catch (NumberFormatException e) {
                    }

                    Log.v(TAG, "Deleting stale thumbnail " + thumbFile);
                    deleteAndInvalidate(thumbFile);
                    prunedCount++;
                }
            }
        }

        // Also delete stale items from legacy tables
        db.execSQL("delete from thumbnails "
                + "where image_id not in (select _id from images)");
        db.execSQL("delete from videothumbnails "
                + "where video_id not in (select _id from video)");

        return prunedCount;
    }

    abstract class Thumbnailer {
        final String directoryName;

        public Thumbnailer(String directoryName) {
            this.directoryName = directoryName;
        }

        private File getThumbnailFile(Uri uri) throws IOException {
            final String volumeName = resolveVolumeName(uri);
            final File volumePath = getVolumePath(volumeName);
            return FileUtils.buildPath(volumePath, directoryName,
                    DIRECTORY_THUMBNAILS, ContentUris.parseId(uri) + ".jpg");
        }

        public abstract Bitmap getThumbnailBitmap(Uri uri, CancellationSignal signal)
                throws IOException;

        public ParcelFileDescriptor ensureThumbnail(Uri uri, CancellationSignal signal)
                throws IOException {
            // First attempt to fast-path by opening the thumbnail; if it
            // doesn't exist we fall through to create it below
            final File thumbFile = getThumbnailFile(uri);
            try {
                return FileUtils.openSafely(thumbFile,
                        ParcelFileDescriptor.MODE_READ_ONLY);
            } catch (FileNotFoundException ignored) {
            }

            final File thumbDir = thumbFile.getParentFile();
            thumbDir.mkdirs();

            // When multiple threads race for the same thumbnail, the second
            // thread could return a file with a thumbnail still in
            // progress. We could add heavy per-ID locking to mitigate this
            // rare race condition, but it's simpler to have both threads
            // generate the same thumbnail using temporary files and rename
            // them into place once finished.
            final File thumbTempFile = File.createTempFile("thumb", null, thumbDir);

            ParcelFileDescriptor thumbWrite = null;
            ParcelFileDescriptor thumbRead = null;
            try {
                // Open our temporary file twice: once for local writing, and
                // once for remote reading. Both FDs point at the same
                // underlying inode on disk, so they're stable across renames
                // to avoid race conditions between threads.
                thumbWrite = FileUtils.openSafely(thumbTempFile,
                        ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_CREATE);
                thumbRead = FileUtils.openSafely(thumbTempFile,
                        ParcelFileDescriptor.MODE_READ_ONLY);

                final Bitmap thumbnail = getThumbnailBitmap(uri, signal);
                thumbnail.compress(Bitmap.CompressFormat.JPEG, 90,
                        new FileOutputStream(thumbWrite.getFileDescriptor()));

                try {
                    // Use direct syscall for better failure logs
                    Os.rename(thumbTempFile.getAbsolutePath(), thumbFile.getAbsolutePath());
                } catch (ErrnoException e) {
                    e.rethrowAsIOException();
                }

                // Everything above went peachy, so return a duplicate of our
                // already-opened read FD to keep our finally logic below simple
                return thumbRead.dup();

            } finally {
                // Regardless of success or failure, try cleaning up any
                // remaining temporary file and close all our local FDs
                FileUtils.closeQuietly(thumbWrite);
                FileUtils.closeQuietly(thumbRead);
                deleteAndInvalidate(thumbTempFile);
            }
        }

        public void invalidateThumbnail(Uri uri) throws IOException {
            deleteAndInvalidate(getThumbnailFile(uri));
        }
    }

    private Thumbnailer mAudioThumbnailer = new Thumbnailer(Environment.DIRECTORY_MUSIC) {
        @Override
        public Bitmap getThumbnailBitmap(Uri uri, CancellationSignal signal) throws IOException {
            return ThumbnailUtils.createAudioThumbnail(queryForDataFile(uri, signal),
                    mThumbSize, signal);
        }
    };

    private Thumbnailer mVideoThumbnailer = new Thumbnailer(Environment.DIRECTORY_MOVIES) {
        @Override
        public Bitmap getThumbnailBitmap(Uri uri, CancellationSignal signal) throws IOException {
            return ThumbnailUtils.createVideoThumbnail(queryForDataFile(uri, signal),
                    mThumbSize, signal);
        }
    };

    private Thumbnailer mImageThumbnailer = new Thumbnailer(Environment.DIRECTORY_PICTURES) {
        @Override
        public Bitmap getThumbnailBitmap(Uri uri, CancellationSignal signal) throws IOException {
            return ThumbnailUtils.createImageThumbnail(queryForDataFile(uri, signal),
                    mThumbSize, signal);
        }
    };

    private List<File> getThumbnailDirectories(MediaVolume volume) throws FileNotFoundException {
        final File volumePath = volume.getPath();
        return Arrays.asList(
                FileUtils.buildPath(volumePath, Environment.DIRECTORY_MUSIC, DIRECTORY_THUMBNAILS),
                FileUtils.buildPath(volumePath, Environment.DIRECTORY_MOVIES, DIRECTORY_THUMBNAILS),
                FileUtils.buildPath(volumePath, Environment.DIRECTORY_PICTURES,
                        DIRECTORY_THUMBNAILS));
    }

    private void invalidateThumbnails(Uri uri) {
        Trace.beginSection("invalidateThumbnails");
        try {
            invalidateThumbnailsInternal(uri);
        } finally {
            Trace.endSection();
        }
    }

    private void invalidateThumbnailsInternal(Uri uri) {
        final long id = ContentUris.parseId(uri);
        try {
            mAudioThumbnailer.invalidateThumbnail(uri);
            mVideoThumbnailer.invalidateThumbnail(uri);
            mImageThumbnailer.invalidateThumbnail(uri);
        } catch (IOException ignored) {
        }

        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(uri);
        } catch (VolumeNotFoundException e) {
            Log.w(TAG, e);
            return;
        }

        helper.runWithTransaction((db) -> {
            final String idString = Long.toString(id);
            try (Cursor c = db.rawQuery("select _data from thumbnails where image_id=?"
                    + " union all select _data from videothumbnails where video_id=?",
                    new String[] { idString, idString })) {
                while (c.moveToNext()) {
                    String path = c.getString(0);
                    deleteIfAllowed(uri, Bundle.EMPTY, path);
                }
            }

            db.execSQL("delete from thumbnails where image_id=?", new String[] { idString });
            db.execSQL("delete from videothumbnails where video_id=?", new String[] { idString });
            return null;
        });
    }

    /**
     * @deprecated all operations should be routed through the overload that
     *             accepts a {@link Bundle} of extras.
     */
    @Override
    @Deprecated
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return update(uri, values,
                DatabaseUtils.createSqlQueryBundle(selection, selectionArgs, null));
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values,
            @Nullable Bundle extras) {
        Trace.beginSection("update");
        try {
            return updateInternal(uri, values, extras);
        } catch (FallbackException e) {
            return e.translateForUpdateDelete(getCallingPackageTargetSdkVersion());
        } finally {
            Trace.endSection();
        }
    }

    private int updateInternal(@NonNull Uri uri, @Nullable ContentValues initialValues,
            @Nullable Bundle extras) throws FallbackException {
        final String volumeName = getVolumeName(uri);
        PulledMetrics.logVolumeAccessViaMediaProvider(getCallingUidOrSelf(), volumeName);

        extras = (extras != null) ? extras : new Bundle();
        // REDACTED_URI_BUNDLE_KEY extra should only be set inside MediaProvider.
        extras.remove(QUERY_ARG_REDACTED_URI);

        if (isRedactedUri(uri)) {
            // we don't support update on redacted uris.
            return 0;
        }

        // Related items are only considered for new media creation, and they
        // can't be leveraged to move existing content into blocked locations
        extras.remove(QUERY_ARG_RELATED_URI);
        // INCLUDED_DEFAULT_DIRECTORIES extra should only be set inside MediaProvider.
        extras.remove(INCLUDED_DEFAULT_DIRECTORIES);

        final String userWhere = extras.getString(QUERY_ARG_SQL_SELECTION);
        final String[] userWhereArgs = extras.getStringArray(QUERY_ARG_SQL_SELECTION_ARGS);

        // Limit the hacky workaround to camera targeting Q and below, to allow newer versions
        // of camera that does the right thing to work correctly.
        if ("com.google.android.GoogleCamera".equals(getCallingPackageOrSelf())
                && getCallingPackageTargetSdkVersion() <= Build.VERSION_CODES.Q) {
            if (matchUri(uri, false) == IMAGES_MEDIA_ID) {
                Log.w(TAG, "Working around app bug in b/111966296");
                uri = MediaStore.Files.getContentUri("external", ContentUris.parseId(uri));
            } else if (matchUri(uri, false) == VIDEO_MEDIA_ID) {
                Log.w(TAG, "Working around app bug in b/112246630");
                uri = MediaStore.Files.getContentUri("external", ContentUris.parseId(uri));
            }
        }

        uri = safeUncanonicalize(uri);

        int count;

        final int targetSdkVersion = getCallingPackageTargetSdkVersion();
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);
        final DatabaseHelper helper = getDatabaseForUri(uri);

        switch (match) {
            case AUDIO_PLAYLISTS_ID_MEMBERS_ID:
                extras.putString(QUERY_ARG_SQL_SELECTION,
                        BaseColumns._ID + "=" + uri.getPathSegments().get(5));
                // fall-through
            case AUDIO_PLAYLISTS_ID_MEMBERS: {
                final long playlistId = Long.parseLong(uri.getPathSegments().get(3));
                final Uri playlistUri = ContentUris.withAppendedId(
                        MediaStore.Audio.Playlists.getContentUri(volumeName), playlistId);
                if (uri.getBooleanQueryParameter("move", false)) {
                    // Convert explicit request into query; sigh, moveItem()
                    // uses zero-based indexing instead of one-based indexing
                    final int from = Integer.parseInt(uri.getPathSegments().get(5)) + 1;
                    final int to = initialValues.getAsInteger(Playlists.Members.PLAY_ORDER) + 1;
                    extras.putString(QUERY_ARG_SQL_SELECTION,
                            Playlists.Members.PLAY_ORDER + "=" + from);
                    initialValues.put(Playlists.Members.PLAY_ORDER, to);
                }

                // Playlist contents are always persisted directly into playlist
                // files on disk to ensure that we can reliably migrate between
                // devices and recover from database corruption
                final int index;
                if (initialValues.containsKey(Playlists.Members.PLAY_ORDER)) {
                    index = movePlaylistMembers(playlistUri, initialValues, extras);
                } else {
                    index = resolvePlaylistIndex(playlistUri, extras);
                }
                if (initialValues.containsKey(Playlists.Members.AUDIO_ID)) {
                    final Bundle queryArgs = new Bundle();
                    queryArgs.putString(QUERY_ARG_SQL_SELECTION,
                            Playlists.Members.PLAY_ORDER + "=" + (index + 1));
                    removePlaylistMembers(playlistUri, queryArgs);

                    final ContentValues values = new ContentValues();
                    values.put(Playlists.Members.AUDIO_ID,
                            initialValues.getAsString(Playlists.Members.AUDIO_ID));
                    values.put(Playlists.Members.PLAY_ORDER, (index + 1));
                    addPlaylistMembers(playlistUri, values);
                }

                acceptWithExpansion(helper::notifyUpdate, volumeName, playlistId,
                        FileColumns.MEDIA_TYPE_PLAYLIST, false);
                return 1;
            }
        }

        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_UPDATE, match, uri, extras, null);

        // Give callers interacting with a specific media item a chance to
        // escalate access if they don't already have it
        switch (match) {
            case AUDIO_MEDIA_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
                enforceCallingPermission(uri, extras, true);
        }

        boolean triggerInvalidate = false;
        boolean triggerScan = false;
        boolean isUriPublished = false;
        if (initialValues != null) {
            // IDs are forever; nobody should be editing them
            initialValues.remove(MediaColumns._ID);

            // Expiration times are hard-coded; let's derive them
            FileUtils.computeDateExpires(initialValues);

            // Ignore or augment incoming raw filesystem paths
            for (String column : sDataColumns.keySet()) {
                if (!initialValues.containsKey(column)) continue;

                if (isCallingPackageSelf() || isCallingPackageLegacyWrite()) {
                    // Mutation allowed
                } else {
                    Log.w(TAG, "Ignoring mutation of  " + column + " from "
                            + getCallingPackageOrSelf());
                    initialValues.remove(column);
                }
            }

            // Enforce allowed ownership transfers
            if (initialValues.containsKey(MediaColumns.OWNER_PACKAGE_NAME)) {
                if (isCallingPackageSelf() || isCallingPackageShell()) {
                    // When the caller is the media scanner or the shell, we let
                    // them change ownership however they see fit; nothing to do
                } else if (isCallingPackageDelegator()) {
                    // When the caller is a delegator, allow them to shift
                    // ownership only when current owner, or when ownerless
                    final String currentOwner;
                    final String proposedOwner = initialValues
                            .getAsString(MediaColumns.OWNER_PACKAGE_NAME);
                    final Uri genericUri = MediaStore.Files.getContentUri(volumeName,
                            ContentUris.parseId(uri));
                    try (Cursor c = queryForSingleItem(genericUri,
                            new String[] { MediaColumns.OWNER_PACKAGE_NAME }, null, null, null)) {
                        currentOwner = c.getString(0);
                    } catch (FileNotFoundException e) {
                        throw new IllegalStateException(e);
                    }
                    final boolean transferAllowed = (currentOwner == null)
                            || Arrays.asList(getSharedPackagesForPackage(getCallingPackageOrSelf()))
                                    .contains(currentOwner);
                    if (transferAllowed) {
                        Log.v(TAG, "Ownership transfer from " + currentOwner + " to "
                                + proposedOwner + " allowed");
                    } else {
                        Log.w(TAG, "Ownership transfer from " + currentOwner + " to "
                                + proposedOwner + " blocked");
                        initialValues.remove(MediaColumns.OWNER_PACKAGE_NAME);
                    }
                } else {
                    // Otherwise no ownership changes are allowed
                    initialValues.remove(MediaColumns.OWNER_PACKAGE_NAME);
                }
            }

            if (!isCallingPackageSelf()) {
                Trace.beginSection("filter");

                // We default to filtering mutable columns, except when we know
                // the single item being updated is pending; when it's finally
                // published we'll overwrite these values.
                final Uri finalUri = uri;
                final Supplier<Boolean> isPending = new CachedSupplier<>(() -> {
                    return isPending(finalUri);
                });

                // Column values controlled by media scanner aren't writable by
                // apps, since any edits here don't reflect the metadata on
                // disk, and they'd be overwritten during a rescan.
                for (String column : new ArraySet<>(initialValues.keySet())) {
                    if (sMutableColumns.contains(column)) {
                        // Mutation normally allowed
                    } else if (isPending.get()) {
                        // Mutation relaxed while pending
                    } else {
                        Log.w(TAG, "Ignoring mutation of " + column + " from "
                                + getCallingPackageOrSelf());
                        initialValues.remove(column);
                        triggerScan = true;
                    }

                    // If we're publishing this item, perform a blocking scan to
                    // make sure metadata is updated
                    if (MediaColumns.IS_PENDING.equals(column)) {
                        triggerScan = true;
                        isUriPublished = true;
                        // Explicitly clear columns used to ignore no-op scans,
                        // since we need to force a scan on publish
                        initialValues.putNull(MediaColumns.DATE_MODIFIED);
                        initialValues.putNull(MediaColumns.SIZE);
                    }
                }

                Trace.endSection();
            }

            if ("files".equals(qb.getTables())) {
                maybeMarkAsDownload(initialValues);
            }

            // We no longer track location metadata
            if (initialValues.containsKey(ImageColumns.LATITUDE)) {
                initialValues.putNull(ImageColumns.LATITUDE);
            }
            if (initialValues.containsKey(ImageColumns.LONGITUDE)) {
                initialValues.putNull(ImageColumns.LONGITUDE);
            }
            if (getCallingPackageTargetSdkVersion() <= Build.VERSION_CODES.Q) {
                // These columns are removed in R.
                if (initialValues.containsKey("primary_directory")) {
                    initialValues.remove("primary_directory");
                }
                if (initialValues.containsKey("secondary_directory")) {
                    initialValues.remove("secondary_directory");
                }
            }
        }

        // If we're not updating anything, then we can skip
        if (initialValues.isEmpty()) return 0;

        final boolean isThumbnail;
        switch (match) {
            case IMAGES_THUMBNAILS:
            case IMAGES_THUMBNAILS_ID:
            case VIDEO_THUMBNAILS:
            case VIDEO_THUMBNAILS_ID:
            case AUDIO_ALBUMART:
            case AUDIO_ALBUMART_ID:
                isThumbnail = true;
                break;
            default:
                isThumbnail = false;
                break;
        }

        switch (match) {
            case AUDIO_PLAYLISTS:
            case AUDIO_PLAYLISTS_ID:
                // Playlist names are stored as display names, but leave
                // values untouched if the caller is ModernMediaScanner
                if (!isCallingPackageSelf()) {
                    if (initialValues.containsKey(Playlists.NAME)) {
                        initialValues.put(MediaColumns.DISPLAY_NAME,
                                initialValues.getAsString(Playlists.NAME));
                    }
                    if (!initialValues.containsKey(MediaColumns.MIME_TYPE)) {
                        initialValues.put(MediaColumns.MIME_TYPE, "audio/mpegurl");
                    }
                }
                break;
        }

        // If we're touching columns that would change placement of a file,
        // blend in current values and recalculate path
        final boolean allowMovement = extras.getBoolean(MediaStore.QUERY_ARG_ALLOW_MOVEMENT,
                !isCallingPackageSelf());
        if (containsAny(initialValues.keySet(), sPlacementColumns)
                && !initialValues.containsKey(MediaColumns.DATA)
                && !isThumbnail
                && allowMovement) {
            Trace.beginSection("movement");

            // We only support movement under well-defined collections
            switch (match) {
                case AUDIO_MEDIA_ID:
                case AUDIO_PLAYLISTS_ID:
                case VIDEO_MEDIA_ID:
                case IMAGES_MEDIA_ID:
                case DOWNLOADS_ID:
                case FILES_ID:
                    break;
                default:
                    throw new IllegalArgumentException("Movement of " + uri
                            + " which isn't part of well-defined collection not allowed");
            }

            final LocalCallingIdentity token = clearLocalCallingIdentity();
            final Uri genericUri = MediaStore.Files.getContentUri(volumeName,
                    ContentUris.parseId(uri));
            try (Cursor c = queryForSingleItem(genericUri,
                    sPlacementColumns.toArray(new String[0]), userWhere, userWhereArgs, null)) {
                for (int i = 0; i < c.getColumnCount(); i++) {
                    final String column = c.getColumnName(i);
                    if (!initialValues.containsKey(column)) {
                        initialValues.put(column, c.getString(i));
                    }
                }
            } catch (FileNotFoundException e) {
                throw new IllegalStateException(e);
            } finally {
                restoreLocalCallingIdentity(token);
            }

            // Regenerate path using blended values; this will throw if caller
            // is attempting to place file into invalid location
            final String beforePath = initialValues.getAsString(MediaColumns.DATA);
            final String beforeVolume = extractVolumeName(beforePath);
            final String beforeOwner = extractPathOwnerPackageName(beforePath);

            initialValues.remove(MediaColumns.DATA);
            ensureNonUniqueFileColumns(match, uri, extras, initialValues, beforePath);

            final String probePath = initialValues.getAsString(MediaColumns.DATA);
            final String probeVolume = extractVolumeName(probePath);
            final String probeOwner = extractPathOwnerPackageName(probePath);
            if (Objects.equals(beforePath, probePath)) {
                Log.d(TAG, "Identical paths " + beforePath + "; not moving");
            } else if (!Objects.equals(beforeVolume, probeVolume)) {
                throw new IllegalArgumentException("Changing volume from " + beforePath + " to "
                        + probePath + " not allowed");
            } else if (!isUpdateAllowedForOwnedPath(beforeOwner, probeOwner, beforePath,
                    probePath)) {
                throw new IllegalArgumentException("Changing ownership from " + beforePath + " to "
                        + probePath + " not allowed");
            } else {
                // Now that we've confirmed an actual movement is taking place,
                // ensure we have a unique destination
                initialValues.remove(MediaColumns.DATA);
                ensureUniqueFileColumns(match, uri, extras, initialValues, beforePath);

                String afterPath = initialValues.getAsString(MediaColumns.DATA);

                if (isCrossUserEnabled()) {
                    String afterVolume = extractVolumeName(afterPath);
                    String afterVolumePath =  extractVolumePath(afterPath);
                    String beforeVolumePath = extractVolumePath(beforePath);

                    if (MediaStore.VOLUME_EXTERNAL_PRIMARY.equals(beforeVolume)
                            && beforeVolume.equals(afterVolume)
                            && !beforeVolumePath.equals(afterVolumePath)) {
                        // On cross-user enabled devices, it can happen that a rename intended as
                        // /storage/emulated/999/foo -> /storage/emulated/999/foo can end up as
                        // /storage/emulated/999/foo -> /storage/emulated/0/foo. We now fix-up
                        afterPath = afterPath.replaceFirst(afterVolumePath, beforeVolumePath);
                    }
                }

                Log.d(TAG, "Moving " + beforePath + " to " + afterPath);
                try {
                    Os.rename(beforePath, afterPath);
                    invalidateFuseDentry(beforePath);
                    invalidateFuseDentry(afterPath);
                } catch (ErrnoException e) {
                    if (e.errno == OsConstants.ENOENT) {
                        Log.d(TAG, "Missing file at " + beforePath + "; continuing anyway");
                    } else {
                        throw new IllegalStateException(e);
                    }
                }
                initialValues.put(MediaColumns.DATA, afterPath);

                // Some indexed metadata may have been derived from the path on
                // disk, so scan this item again to update it
                triggerScan = true;
            }

            Trace.endSection();
        }

        assertPrivatePathNotInValues(initialValues);

        // Make sure any updated paths look consistent
        assertFileColumnsConsistent(match, uri, initialValues);

        if (initialValues.containsKey(FileColumns.DATA)) {
            // If we're changing paths, invalidate any thumbnails
            triggerInvalidate = true;

            // If the new file exists, trigger a scan to adjust any metadata
            // that might be derived from the path
            final String data = initialValues.getAsString(FileColumns.DATA);
            if (!TextUtils.isEmpty(data) && new File(data).exists()) {
                triggerScan = true;
            }
        }

        // If we're already doing this update from an internal scan, no need to
        // kick off another no-op scan
        if (isCallingPackageSelf()) {
            triggerScan = false;
        }

        // Since the update mutation may prevent us from matching items after
        // it's applied, we need to snapshot affected IDs here
        final LongArray updatedIds = new LongArray();
        if (triggerInvalidate || triggerScan) {
            Trace.beginSection("snapshot");
            final LocalCallingIdentity token = clearLocalCallingIdentity();
            try (Cursor c = qb.query(helper, new String[] { FileColumns._ID },
                    userWhere, userWhereArgs, null, null, null, null, null)) {
                while (c.moveToNext()) {
                    updatedIds.add(c.getLong(0));
                }
            } finally {
                restoreLocalCallingIdentity(token);
                Trace.endSection();
            }
        }

        final ContentValues values = new ContentValues(initialValues);
        switch (match) {
            case AUDIO_MEDIA_ID:
            case AUDIO_PLAYLISTS_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
            case FILES_ID:
            case DOWNLOADS_ID: {
                FileUtils.computeValuesFromData(values, isFuseThread());
                break;
            }
        }

        if (initialValues.containsKey(FileColumns.MEDIA_TYPE)) {
            final int mediaType = initialValues.getAsInteger(FileColumns.MEDIA_TYPE);
            switch (mediaType) {
                case FileColumns.MEDIA_TYPE_AUDIO: {
                    computeAudioLocalizedValues(values);
                    computeAudioKeyValues(values);
                    break;
                }
            }
        }

        boolean deferScan = false;
        if (triggerScan) {
            if (SdkLevel.isAtLeastS() &&
                    CompatChanges.isChangeEnabled(ENABLE_DEFERRED_SCAN, Binder.getCallingUid())) {
                if (extras.containsKey(QUERY_ARG_DO_ASYNC_SCAN)) {
                    throw new IllegalArgumentException("Unsupported argument " +
                            QUERY_ARG_DO_ASYNC_SCAN + " used in extras");
                }
                deferScan = extras.getBoolean(QUERY_ARG_DEFER_SCAN, false);
                if (deferScan && initialValues.containsKey(MediaColumns.IS_PENDING) &&
                        (initialValues.getAsInteger(MediaColumns.IS_PENDING) == 1)) {
                    // if the scan runs in async, ensure that the database row is excluded in
                    // default query until the metadata is updated by deferred scan.
                    // Apps will still be able to see this database row when queried with
                    // QUERY_ARG_MATCH_PENDING=MATCH_INCLUDE
                    values.put(FileColumns._MODIFIER, FileColumns._MODIFIER_CR_PENDING_METADATA);
                    qb.allowColumn(FileColumns._MODIFIER);
                }
            } else {
                // Allow apps to use QUERY_ARG_DO_ASYNC_SCAN if the device is R or app is targeting
                // targetSDK<=R.
                deferScan = extras.getBoolean(QUERY_ARG_DO_ASYNC_SCAN, false);
            }
        }

        count = updateAllowingReplace(qb, helper, values, userWhere, userWhereArgs);

        // If the caller tried (and failed) to update metadata, the file on disk
        // might have changed, to scan it to collect the latest metadata.
        if (triggerInvalidate || triggerScan) {
            Trace.beginSection("invalidate");
            final LocalCallingIdentity token = clearLocalCallingIdentity();
            try {
                for (int i = 0; i < updatedIds.size(); i++) {
                    final long updatedId = updatedIds.get(i);
                    final Uri updatedUri = Files.getContentUri(volumeName, updatedId);
                    helper.postBackground(() -> {
                        invalidateThumbnails(updatedUri);
                    });

                    if (triggerScan) {
                        try (Cursor c = queryForSingleItem(updatedUri,
                                new String[] { FileColumns.DATA }, null, null, null)) {
                            final File file = new File(c.getString(0));
                            final boolean notifyTranscodeHelper = isUriPublished;
                            if (deferScan) {
                                helper.postBackground(() -> {
                                    scanFileAsMediaProvider(file, REASON_DEMAND);
                                    if (notifyTranscodeHelper) {
                                        notifyTranscodeHelperOnUriPublished(updatedUri);
                                    }
                                });
                            } else {
                                helper.postBlocking(() -> {
                                    scanFileAsMediaProvider(file, REASON_DEMAND);
                                    if (notifyTranscodeHelper) {
                                        notifyTranscodeHelperOnUriPublished(updatedUri);
                                    }
                                });
                            }
                        } catch (Exception e) {
                            Log.w(TAG, "Failed to update metadata for " + updatedUri, e);
                        }
                    }
                }
            } finally {
                restoreLocalCallingIdentity(token);
                Trace.endSection();
            }
        }

        return count;
    }

    private boolean isUpdateAllowedForOwnedPath(@Nullable String srcOwner,
            @Nullable String destOwner, @NonNull String srcPath, @NonNull String destPath) {
        // 1. Allow if the update is within owned path
        // update() from /sdcard/Android/media/com.foo/ABC/image.jpeg to
        // /sdcard/Android/media/com.foo/XYZ/image.jpeg - Allowed
        if(Objects.equals(srcOwner, destOwner)) {
            return true;
        }

        // 2. Check if the calling package is a special app which has global access
        if (isCallingPackageManager() ||
                (canAccessMediaFile(srcPath, /* excludeNonSystemGallery */ true) &&
                        (canAccessMediaFile(destPath, /* excludeNonSystemGallery */ true)))) {
            return true;
        }

        // 3. Allow update from srcPath if the source is not a owned path or calling package is the
        // owner of the source path or calling package shares the UID with the owner of the source
        // path
        // update() from /sdcard/DCIM/Foo.jpeg - Allowed
        // update() from /sdcard/Android/media/com.foo/image.jpeg - Allowed for
        // callingPackage=com.foo, not allowed for callingPackage=com.bar
        final boolean isSrcUpdateAllowed = srcOwner == null
                || isCallingIdentitySharedPackageName(srcOwner);

        // 4. Allow update to dstPath if the destination is not a owned path or calling package is
        // the owner of the destination path or calling package shares the UID with the owner of the
        // destination path
        // update() to /sdcard/Pictures/image.jpeg - Allowed
        // update() to /sdcard/Android/media/com.foo/image.jpeg - Allowed for
        // callingPackage=com.foo, not allowed for callingPackage=com.bar
        final boolean isDestUpdateAllowed = destOwner == null
                || isCallingIdentitySharedPackageName(destOwner);

        return isSrcUpdateAllowed && isDestUpdateAllowed;
    }

    private void notifyTranscodeHelperOnUriPublished(Uri uri) {
        BackgroundThread.getExecutor().execute(() -> {
            final LocalCallingIdentity token = clearLocalCallingIdentity();
            try {
                mTranscodeHelper.onUriPublished(uri);
            } finally {
                restoreLocalCallingIdentity(token);
            }
        });
    }

    private void notifyTranscodeHelperOnFileOpen(String path, String ioPath, int uid,
            int transformsReason) {
        BackgroundThread.getExecutor().execute(() -> {
            final LocalCallingIdentity token = clearLocalCallingIdentity();
            try {
                mTranscodeHelper.onFileOpen(path, ioPath, uid, transformsReason);
            } finally {
                restoreLocalCallingIdentity(token);
            }
        });
    }

    /**
     * Update row(s) that match {@code userWhere} in MediaProvider database with {@code values}.
     * Treats update as replace for updates with conflicts.
     */
    private int updateAllowingReplace(@NonNull SQLiteQueryBuilder qb,
            @NonNull DatabaseHelper helper, @NonNull ContentValues values, String userWhere,
            String[] userWhereArgs) throws SQLiteConstraintException {
        return helper.runWithTransaction((db) -> {
            try {
                return qb.update(helper, values, userWhere, userWhereArgs);
            } catch (SQLiteConstraintException e) {
                // b/155320967 Apps sometimes create a file via file path and then update another
                // explicitly inserted db row to this file. We have to resolve this update with a
                // replace.

                if (getCallingPackageTargetSdkVersion() >= Build.VERSION_CODES.R) {
                    // We don't support replace for non-legacy apps. Non legacy apps should have
                    // clearer interactions with MediaProvider.
                    throw e;
                }

                final String path = values.getAsString(FileColumns.DATA);

                // We will only handle UNIQUE constraint error for FileColumns.DATA. We will not try
                // update and replace if no file exists for conflicting db row.
                if (path == null || !new File(path).exists()) {
                    throw e;
                }

                final Uri uri = FileUtils.getContentUriForPath(path);
                final boolean allowHidden = isCallingPackageAllowedHidden();
                // The db row which caused UNIQUE constraint error may not match all column values
                // of the given queryBuilder, hence using a generic queryBuilder with Files uri.
                Bundle extras = new Bundle();
                extras.putInt(QUERY_ARG_MATCH_PENDING, MATCH_INCLUDE);
                extras.putInt(QUERY_ARG_MATCH_TRASHED, MATCH_INCLUDE);
                final SQLiteQueryBuilder qbForReplace = getQueryBuilder(TYPE_DELETE,
                        matchUri(uri, allowHidden), uri, extras, null);
                final long rowId = getIdIfPathOwnedByPackages(qbForReplace, helper, path,
                        getSharedPackages());

                if (rowId != -1 && qbForReplace.delete(helper, "_id=?",
                        new String[] {Long.toString(rowId)}) == 1) {
                    Log.i(TAG, "Retrying database update after deleting conflicting entry");
                    return qb.update(helper, values, userWhere, userWhereArgs);
                }
                // Rethrow SQLiteConstraintException if app doesn't own the conflicting db row.
                throw e;
            }
        });
    }

    /**
     * Update the internal table of {@link MediaStore.Audio.Playlists.Members}
     * by parsing the playlist file on disk and resolving it against scanned
     * audio items.
     * <p>
     * When a playlist references a missing audio item, the associated
     * {@link Playlists.Members#PLAY_ORDER} is skipped, leaving a gap to ensure
     * that the playlist entry is retained to avoid user data loss.
     */
    private void resolvePlaylistMembers(@NonNull Uri playlistUri) {
        Trace.beginSection("resolvePlaylistMembers");
        try {
            final DatabaseHelper helper;
            try {
                helper = getDatabaseForUri(playlistUri);
            } catch (VolumeNotFoundException e) {
                throw e.rethrowAsIllegalArgumentException();
            }

            helper.runWithTransaction((db) -> {
                resolvePlaylistMembersInternal(playlistUri, db);
                return null;
            });
        } finally {
            Trace.endSection();
        }
    }

    private void resolvePlaylistMembersInternal(@NonNull Uri playlistUri,
            @NonNull SQLiteDatabase db) {
        try {
            // Refresh playlist members based on what we parse from disk
            final long playlistId = ContentUris.parseId(playlistUri);
            final Map<String, Long> membersMap = getAllPlaylistMembers(playlistId);
            db.delete("audio_playlists_map", "playlist_id=" + playlistId, null);

            final Path playlistPath = queryForDataFile(playlistUri, null).toPath();
            final Playlist playlist = new Playlist();
            playlist.read(playlistPath.toFile());

            final List<Path> members = playlist.asList();
            for (int i = 0; i < members.size(); i++) {
                try {
                    final Path audioPath = playlistPath.getParent().resolve(members.get(i));
                    final long audioId = queryForPlaylistMember(audioPath, membersMap);

                    final ContentValues values = new ContentValues();
                    values.put(Playlists.Members.PLAY_ORDER, i + 1);
                    values.put(Playlists.Members.PLAYLIST_ID, playlistId);
                    values.put(Playlists.Members.AUDIO_ID, audioId);
                    db.insert("audio_playlists_map", null, values);
                } catch (IOException e) {
                    Log.w(TAG, "Failed to resolve playlist member", e);
                }
            }
        } catch (IOException e) {
            Log.w(TAG, "Failed to refresh playlist", e);
        }
    }

    private Map<String, Long> getAllPlaylistMembers(long playlistId) {
        final Map<String, Long> membersMap = new ArrayMap<>();

        final Uri uri = Playlists.Members.getContentUri(MediaStore.VOLUME_EXTERNAL, playlistId);
        final String[] projection = new String[] {
                Playlists.Members.DATA,
                Playlists.Members.AUDIO_ID
        };
        try (Cursor c = query(uri, projection, null, null)) {
            if (c == null) {
                Log.e(TAG, "Cursor is null, failed to create cached playlist member info.");
                return membersMap;
            }
            while (c.moveToNext()) {
                membersMap.put(c.getString(0), c.getLong(1));
            }
        }
        return membersMap;
    }

    /**
     * Make two attempts to query this playlist member: first based on the exact
     * path, and if that fails, fall back to picking a single item matching the
     * display name. When there are multiple items with the same display name,
     * we can't resolve between them, and leave this member unresolved.
     */
    private long queryForPlaylistMember(@NonNull Path path, @NonNull Map<String, Long> membersMap)
            throws IOException {
        final String data = path.toFile().getCanonicalPath();
        if (membersMap.containsKey(data)) {
            return membersMap.get(data);
        }
        final Uri audioUri = Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
        try (Cursor c = queryForSingleItem(audioUri,
                new String[] { BaseColumns._ID }, MediaColumns.DATA + "=?",
                new String[] { data }, null)) {
            return c.getLong(0);
        } catch (FileNotFoundException ignored) {
        }
        try (Cursor c = queryForSingleItem(audioUri,
                new String[] { BaseColumns._ID }, MediaColumns.DISPLAY_NAME + "=?",
                new String[] { path.toFile().getName() }, null)) {
            return c.getLong(0);
        } catch (FileNotFoundException ignored) {
        }
        throw new FileNotFoundException();
    }

    /**
     * Add the given audio item to the given playlist. Defaults to adding at the
     * end of the playlist when no {@link Playlists.Members#PLAY_ORDER} is
     * defined.
     */
    private long addPlaylistMembers(@NonNull Uri playlistUri, @NonNull ContentValues values)
            throws FallbackException {
        final long audioId = values.getAsLong(Audio.Playlists.Members.AUDIO_ID);
        final String volumeName = MediaStore.VOLUME_INTERNAL.equals(getVolumeName(playlistUri))
                ? MediaStore.VOLUME_INTERNAL : MediaStore.VOLUME_EXTERNAL;
        final Uri audioUri = Audio.Media.getContentUri(volumeName, audioId);

        Integer playOrder = values.getAsInteger(Playlists.Members.PLAY_ORDER);
        playOrder = (playOrder != null) ? (playOrder - 1) : Integer.MAX_VALUE;

        try {
            final File playlistFile = queryForDataFile(playlistUri, null);
            final File audioFile = queryForDataFile(audioUri, null);

            final Playlist playlist = new Playlist();
            playlist.read(playlistFile);
            playOrder = playlist.add(playOrder,
                    playlistFile.toPath().getParent().relativize(audioFile.toPath()));
            playlist.write(playlistFile);
            invalidateFuseDentry(playlistFile);

            resolvePlaylistMembers(playlistUri);

            // Callers are interested in the actual ID we generated
            final Uri membersUri = Playlists.Members.getContentUri(volumeName,
                    ContentUris.parseId(playlistUri));
            try (Cursor c = query(membersUri, new String[] { BaseColumns._ID },
                    Playlists.Members.PLAY_ORDER + "=" + (playOrder + 1), null, null)) {
                c.moveToFirst();
                return c.getLong(0);
            }
        } catch (IOException e) {
            throw new FallbackException("Failed to update playlist", e,
                    android.os.Build.VERSION_CODES.R);
        }
    }

    private int addPlaylistMembers(@NonNull Uri playlistUri, @NonNull ContentValues[] initialValues)
            throws FallbackException {
        final String volumeName = getVolumeName(playlistUri);
        final String audioVolumeName =
                MediaStore.VOLUME_INTERNAL.equals(volumeName)
                        ? MediaStore.VOLUME_INTERNAL : MediaStore.VOLUME_EXTERNAL;

        try {
            final File playlistFile = queryForDataFile(playlistUri, null);
            final Playlist playlist = new Playlist();
            playlist.read(playlistFile);

            for (ContentValues values : initialValues) {
                final long audioId = values.getAsLong(Audio.Playlists.Members.AUDIO_ID);
                final Uri audioUri = Audio.Media.getContentUri(audioVolumeName, audioId);
                final File audioFile = queryForDataFile(audioUri, null);

                Integer playOrder = values.getAsInteger(Playlists.Members.PLAY_ORDER);
                playOrder = (playOrder != null) ? (playOrder - 1) : Integer.MAX_VALUE;
                playlist.add(playOrder,
                        playlistFile.toPath().getParent().relativize(audioFile.toPath()));
            }
            playlist.write(playlistFile);

            resolvePlaylistMembers(playlistUri);
        } catch (IOException e) {
            throw new FallbackException("Failed to update playlist", e,
                    android.os.Build.VERSION_CODES.R);
        }

        return initialValues.length;
    }

    /**
     * Move an audio item within the given playlist.
     */
    private int movePlaylistMembers(@NonNull Uri playlistUri, @NonNull ContentValues values,
            @NonNull Bundle queryArgs) throws FallbackException {
        final int fromIndex = resolvePlaylistIndex(playlistUri, queryArgs);
        final int toIndex = values.getAsInteger(Playlists.Members.PLAY_ORDER) - 1;
        if (fromIndex == -1) {
            throw new FallbackException("Failed to resolve playlist member " + queryArgs,
                    android.os.Build.VERSION_CODES.R);
        }
        try {
            final File playlistFile = queryForDataFile(playlistUri, null);

            final Playlist playlist = new Playlist();
            playlist.read(playlistFile);
            final int finalIndex = playlist.move(fromIndex, toIndex);
            playlist.write(playlistFile);
            invalidateFuseDentry(playlistFile);

            resolvePlaylistMembers(playlistUri);
            return finalIndex;
        } catch (IOException e) {
            throw new FallbackException("Failed to update playlist", e,
                    android.os.Build.VERSION_CODES.R);
        }
    }

    /**
     * Removes an audio item or multiple audio items(if targetSDK<R) from the given playlist.
     */
    private int removePlaylistMembers(@NonNull Uri playlistUri, @NonNull Bundle queryArgs)
            throws FallbackException {
        final int[] indexes = resolvePlaylistIndexes(playlistUri, queryArgs);
        try {
            final File playlistFile = queryForDataFile(playlistUri, null);

            final Playlist playlist = new Playlist();
            playlist.read(playlistFile);
            final int count;
            if (indexes.length == 0) {
                // This means either no playlist members match the query or VolumeNotFoundException
                // was thrown. So we don't have anything to delete.
                count = 0;
            } else {
                count = playlist.removeMultiple(indexes);
            }
            playlist.write(playlistFile);
            invalidateFuseDentry(playlistFile);

            resolvePlaylistMembers(playlistUri);
            return count;
        } catch (IOException e) {
            throw new FallbackException("Failed to update playlist", e,
                    android.os.Build.VERSION_CODES.R);
        }
    }

    /**
     * Remove an audio item from the given playlist since the playlist file or the audio file is
     * already removed.
     */
    private void removePlaylistMembers(int mediaType, long id) {
        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(Audio.Media.EXTERNAL_CONTENT_URI);
        } catch (VolumeNotFoundException e) {
            Log.w(TAG, e);
            return;
        }

        helper.runWithTransaction((db) -> {
            final String where;
            if (mediaType == FileColumns.MEDIA_TYPE_PLAYLIST) {
                where = "playlist_id=?";
            } else {
                where = "audio_id=?";
            }
            db.delete("audio_playlists_map", where, new String[] { "" + id });
            return null;
        });
    }

    /**
     * Resolve query arguments that are designed to select specific playlist
     * items using the playlist's {@link Playlists.Members#PLAY_ORDER}.
     *
     * @return an array of the indexes that match the query.
     */
    private int[] resolvePlaylistIndexes(@NonNull Uri playlistUri, @NonNull Bundle queryArgs) {
        final Uri membersUri = Playlists.Members.getContentUri(
                getVolumeName(playlistUri), ContentUris.parseId(playlistUri));

        final DatabaseHelper helper;
        final SQLiteQueryBuilder qb;
        try {
            helper = getDatabaseForUri(membersUri);
            qb = getQueryBuilder(TYPE_DELETE, AUDIO_PLAYLISTS_ID_MEMBERS,
                    membersUri, queryArgs, null);
        } catch (VolumeNotFoundException ignored) {
            return new int[0];
        }

        try (Cursor c = qb.query(helper,
                new String[] { Playlists.Members.PLAY_ORDER }, queryArgs, null)) {
            if ((c.getCount() >= 1) && c.moveToFirst()) {
                int size = c.getCount();
                int[] res = new int[size];
                for (int i = 0; i < size; ++i) {
                    res[i] = c.getInt(0) - 1;
                    c.moveToNext();
                }
                return res;
            } else {
                // Cursor size is 0
                return new int[0];
            }
        }
    }

    /**
     * Resolve query arguments that are designed to select a specific playlist
     * item using its {@link Playlists.Members#PLAY_ORDER}.
     *
     * @return if there's only 1 item that matches the query, returns its index. Returns -1
     * otherwise.
     */
    private int resolvePlaylistIndex(@NonNull Uri playlistUri, @NonNull Bundle queryArgs) {
        int[] indexes = resolvePlaylistIndexes(playlistUri, queryArgs);
        if (indexes.length == 1) {
            return indexes[0];
        }
        return -1;
    }

    private boolean isPickerUri(Uri uri) {
        // TODO(b/188394433): move this method to PickerResolver in the spirit of not
        // adding picker logic to MediaProvider
        final int match = matchUri(uri, /* allowHidden */ isCallingPackageAllowedHidden());
        return match == PICKER_ID;
    }

    public boolean isPickerUnreliableVolumeUri(Uri uri, boolean allowHidden) {
        final int match = matchUri(uri, allowHidden);
        return match == PICKER_UNRELIABLE_VOLUME;
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
        return openFileCommon(uri, mode, /*signal*/ null, /*opts*/ null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
            throws FileNotFoundException {
        return openFileCommon(uri, mode, signal, /*opts*/ null);
    }

    private ParcelFileDescriptor openFileCommon(Uri uri, String mode, CancellationSignal signal,
            @Nullable Bundle opts)
            throws FileNotFoundException {
        opts = opts == null ? new Bundle() : opts;
        // REDACTED_URI_BUNDLE_KEY extra should only be set inside MediaProvider.
        opts.remove(QUERY_ARG_REDACTED_URI);
        if (isRedactedUri(uri)) {
            opts.putParcelable(QUERY_ARG_REDACTED_URI, uri);
            uri = getUriForRedactedUri(uri);
        }
        uri = safeUncanonicalize(uri);

        if (isPickerUri(uri)) {
            final int callingPid = mCallingIdentity.get().pid;
            final int callingUid = mCallingIdentity.get().uid;
            return mPickerUriResolver.openFile(uri, mode, signal, callingPid, callingUid);
        }

        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);
        final String volumeName = getVolumeName(uri);

        // Handle some legacy cases where we need to redirect thumbnails
        try {
            switch (match) {
                case AUDIO_ALBUMART_ID: {
                    final long albumId = Long.parseLong(uri.getPathSegments().get(3));
                    final Uri targetUri = ContentUris
                            .withAppendedId(Audio.Albums.getContentUri(volumeName), albumId);
                    return ensureThumbnail(targetUri, signal);
                }
                case AUDIO_ALBUMART_FILE_ID: {
                    final long audioId = Long.parseLong(uri.getPathSegments().get(3));
                    final Uri targetUri = ContentUris
                            .withAppendedId(Audio.Media.getContentUri(volumeName), audioId);
                    return ensureThumbnail(targetUri, signal);
                }
                case VIDEO_MEDIA_ID_THUMBNAIL: {
                    final long videoId = Long.parseLong(uri.getPathSegments().get(3));
                    final Uri targetUri = ContentUris
                            .withAppendedId(Video.Media.getContentUri(volumeName), videoId);
                    return ensureThumbnail(targetUri, signal);
                }
                case IMAGES_MEDIA_ID_THUMBNAIL: {
                    final long imageId = Long.parseLong(uri.getPathSegments().get(3));
                    final Uri targetUri = ContentUris
                            .withAppendedId(Images.Media.getContentUri(volumeName), imageId);
                    return ensureThumbnail(targetUri, signal);
                }
            }
        } finally {
            // We have to log separately here because openFileAndEnforcePathPermissionsHelper calls
            // a public MediaProvider API and so logs the access there.
            PulledMetrics.logVolumeAccessViaMediaProvider(getCallingUidOrSelf(), volumeName);
        }

        return openFileAndEnforcePathPermissionsHelper(uri, match, mode, signal, opts);
    }

    @Override
    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
            throws FileNotFoundException {
        return openTypedAssetFileCommon(uri, mimeTypeFilter, opts, null);
    }

    @Override
    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts,
            CancellationSignal signal) throws FileNotFoundException {
        return openTypedAssetFileCommon(uri, mimeTypeFilter, opts, signal);
    }

    private AssetFileDescriptor openTypedAssetFileCommon(Uri uri, String mimeTypeFilter,
            Bundle opts, CancellationSignal signal) throws FileNotFoundException {
        final boolean wantsThumb = (opts != null) && opts.containsKey(ContentResolver.EXTRA_SIZE)
                && StringUtils.startsWithIgnoreCase(mimeTypeFilter, "image/");
        String mode = "r";

        // If request is not for thumbnail and arising from MediaProvider, then check for EXTRA_MODE
        if (opts != null && !wantsThumb && isCallingPackageSelf()) {
            mode = opts.getString(MediaStore.EXTRA_MODE, "r");
        } else if (opts != null) {
            opts.remove(MediaStore.EXTRA_MODE);
        }

        if (opts != null && opts.containsKey(MediaStore.EXTRA_FILE_DESCRIPTOR)) {
            // This is called as part of MediaStore#getOriginalMediaFormatFileDescriptor
            // We don't need to use the |uri| because the input fd already identifies the file and
            // we actually don't have a valid URI, we are going to identify the file via the fd.
            // While identifying the file, we also perform the following security checks.
            // 1. Find the FUSE file with the associated inode
            // 2. Verify that the binder caller opened it
            // 3. Verify the access level the fd is opened with (r/w)
            // 4. Open the original (non-transcoded) file *with* redaction enabled and the access
            // level from #3
            // 5. Return the fd from #4 to the app or throw an exception if any of the conditions
            // are not met
            try {
                return getOriginalMediaFormatFileDescriptor(opts);
            } finally {
                // Clearing the Bundle closes the underlying Parcel, ensuring that the input fd
                // owned by the Parcel is closed immediately and not at the next GC.
                // This works around a change in behavior introduced by:
                // aosp/Icfe8880cad00c3cd2afcbe4b92400ad4579e680e
                opts.clear();
            }
        }

        // This is needed for thumbnail resolution as it doesn't go through openFileCommon
        if (isPickerUri(uri)) {
            final int callingPid = mCallingIdentity.get().pid;
            final int callingUid = mCallingIdentity.get().uid;
            return mPickerUriResolver.openTypedAssetFile(uri, mimeTypeFilter, opts, signal,
                    callingPid, callingUid);
        }

        // TODO: enforce that caller has access to this uri

        // Offer thumbnail of media, when requested
        if (wantsThumb) {
            final ParcelFileDescriptor pfd = ensureThumbnail(uri, signal);
            return new AssetFileDescriptor(pfd, 0, AssetFileDescriptor.UNKNOWN_LENGTH);
        }

        // Worst case, return the underlying file
        return new AssetFileDescriptor(openFileCommon(uri, mode, signal, opts), 0,
                AssetFileDescriptor.UNKNOWN_LENGTH);
    }

    private ParcelFileDescriptor ensureThumbnail(Uri uri, CancellationSignal signal)
            throws FileNotFoundException {
        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int match = matchUri(uri, allowHidden);

        Trace.beginSection("ensureThumbnail");
        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try {
            switch (match) {
                case AUDIO_ALBUMS_ID: {
                    final String volumeName = MediaStore.getVolumeName(uri);
                    final Uri baseUri = MediaStore.Audio.Media.getContentUri(volumeName);
                    final long albumId = ContentUris.parseId(uri);
                    try (Cursor c = query(baseUri, new String[] { MediaStore.Audio.Media._ID },
                            MediaStore.Audio.Media.ALBUM_ID + "=" + albumId, null, null, signal)) {
                        if (c.moveToFirst()) {
                            final long audioId = c.getLong(0);
                            final Uri targetUri = ContentUris.withAppendedId(baseUri, audioId);
                            return mAudioThumbnailer.ensureThumbnail(targetUri, signal);
                        } else {
                            throw new FileNotFoundException("No media for album " + uri);
                        }
                    }
                }
                case AUDIO_MEDIA_ID:
                    return mAudioThumbnailer.ensureThumbnail(uri, signal);
                case VIDEO_MEDIA_ID:
                    return mVideoThumbnailer.ensureThumbnail(uri, signal);
                case IMAGES_MEDIA_ID:
                    return mImageThumbnailer.ensureThumbnail(uri, signal);
                case FILES_ID:
                case DOWNLOADS_ID: {
                    // When item is referenced in a generic way, resolve to actual type
                    final int mediaType = MimeUtils.resolveMediaType(getType(uri));
                    switch (mediaType) {
                        case FileColumns.MEDIA_TYPE_AUDIO:
                            return mAudioThumbnailer.ensureThumbnail(uri, signal);
                        case FileColumns.MEDIA_TYPE_VIDEO:
                            return mVideoThumbnailer.ensureThumbnail(uri, signal);
                        case FileColumns.MEDIA_TYPE_IMAGE:
                            return mImageThumbnailer.ensureThumbnail(uri, signal);
                        default:
                            throw new FileNotFoundException();
                    }
                }
                default:
                    throw new FileNotFoundException();
            }
        } catch (IOException e) {
            Log.w(TAG, e);
            throw new FileNotFoundException(e.getMessage());
        } finally {
            restoreLocalCallingIdentity(token);
            Trace.endSection();
        }
    }

    /**
     * Update the metadata columns for the image residing at given {@link Uri}
     * by reading data from the underlying image.
     */
    private void updateImageMetadata(ContentValues values, File file) {
        final BitmapFactory.Options bitmapOpts = new BitmapFactory.Options();
        bitmapOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(file.getAbsolutePath(), bitmapOpts);

        values.put(MediaColumns.WIDTH, bitmapOpts.outWidth);
        values.put(MediaColumns.HEIGHT, bitmapOpts.outHeight);
    }

    private void handleInsertedRowForFuse(long rowId) {
        if (isFuseThread()) {
            // Removes restored row ID saved list.
            mCallingIdentity.get().removeDeletedRowId(rowId);
        }
    }

    private void handleUpdatedRowForFuse(@NonNull String oldPath, @NonNull String ownerPackage,
            long oldRowId, long newRowId) {
        if (oldRowId == newRowId) {
            // Update didn't delete or add row ID. We don't need to save row ID or remove saved
            // deleted ID.
            return;
        }

        handleDeletedRowForFuse(oldPath, ownerPackage, oldRowId);
        handleInsertedRowForFuse(newRowId);
    }

    private void handleDeletedRowForFuse(@NonNull String path, @NonNull String ownerPackage,
            long rowId) {
        if (!isFuseThread()) {
            return;
        }

        // Invalidate saved owned ID's of the previous owner of the deleted path, this prevents old
        // owner from gaining access to newly created file with restored row ID.
        if (!ownerPackage.equals("null") && !ownerPackage.equals(getCallingPackageOrSelf())) {
            invalidateLocalCallingIdentityCache(ownerPackage, "owned_database_row_deleted:"
                    + path);
        }
        // Saves row ID corresponding to deleted path. Saved row ID will be restored on subsequent
        // create or rename.
        mCallingIdentity.get().addDeletedRowId(path, rowId);
    }

    private void handleOwnerPackageNameChange(@NonNull String oldPath,
            @NonNull String oldOwnerPackage, @NonNull String newOwnerPackage) {
        if (Objects.equals(oldOwnerPackage, newOwnerPackage)) {
            return;
        }
        // Invalidate saved owned ID's of the previous owner of the renamed path, this prevents old
        // owner from gaining access to replaced file.
        invalidateLocalCallingIdentityCache(oldOwnerPackage, "owner_package_changed:" + oldPath);
    }

    /**
     * Return the {@link MediaColumns#DATA} field for the given {@code Uri}.
     */
    File queryForDataFile(Uri uri, CancellationSignal signal)
            throws FileNotFoundException {
        return queryForDataFile(uri, null, null, signal);
    }

    /**
     * Return the {@link MediaColumns#DATA} field for the given {@code Uri}.
     */
    File queryForDataFile(Uri uri, String selection, String[] selectionArgs,
            CancellationSignal signal) throws FileNotFoundException {
        try (Cursor cursor = queryForSingleItem(uri, new String[] { MediaColumns.DATA },
                selection, selectionArgs, signal)) {
            final String data = cursor.getString(0);
            if (TextUtils.isEmpty(data)) {
                throw new FileNotFoundException("Missing path for " + uri);
            } else {
                return new File(data);
            }
        }
    }

    /**
     * Return the {@link Uri} for the given {@code File}.
     */
    Uri queryForMediaUri(File file, CancellationSignal signal) throws FileNotFoundException {
        final String volumeName = FileUtils.getVolumeName(getContext(), file);
        final Uri uri = Files.getContentUri(volumeName);
        try (Cursor cursor = queryForSingleItem(uri, new String[] { MediaColumns._ID },
                MediaColumns.DATA + "=?", new String[] { file.getAbsolutePath() }, signal)) {
            return ContentUris.withAppendedId(uri, cursor.getLong(0));
        }
    }

    /**
     * Query the given {@link Uri} as MediaProvider, expecting only a single item to be found.
     *
     * @throws FileNotFoundException if no items were found, or multiple items
     *             were found, or there was trouble reading the data.
     */
    Cursor queryForSingleItemAsMediaProvider(Uri uri, String[] projection, String selection,
            String[] selectionArgs, CancellationSignal signal)
            throws FileNotFoundException {
        final LocalCallingIdentity tokenInner = clearLocalCallingIdentity();
        try {
            return queryForSingleItem(uri, projection, selection, selectionArgs, signal);
        } finally {
            restoreLocalCallingIdentity(tokenInner);
        }
    }

    /**
     * Query the given {@link Uri}, expecting only a single item to be found.
     *
     * @throws FileNotFoundException if no items were found, or multiple items
     *             were found, or there was trouble reading the data.
     */
    Cursor queryForSingleItem(Uri uri, String[] projection, String selection,
            String[] selectionArgs, CancellationSignal signal) throws FileNotFoundException {
        Cursor c = null;
        try {
            c = query(uri, projection,
                    DatabaseUtils.createSqlQueryBundle(selection, selectionArgs, null),
                    signal, true);
        } catch (IllegalArgumentException  e) {
            throw new FileNotFoundException("Volume not found for " + uri);
        }
        if (c == null) {
            throw new FileNotFoundException("Missing cursor for " + uri);
        } else if (c.getCount() < 1) {
            FileUtils.closeQuietly(c);
            throw new FileNotFoundException("No item at " + uri);
        } else if (c.getCount() > 1) {
            FileUtils.closeQuietly(c);
            throw new FileNotFoundException("Multiple items at " + uri);
        }

        if (c.moveToFirst()) {
            return c;
        } else {
            FileUtils.closeQuietly(c);
            throw new FileNotFoundException("Failed to read row from " + uri);
        }
    }

    /**
     * Compares {@code itemOwner} with package name of {@link LocalCallingIdentity} and throws
     * {@link IllegalStateException} if it doesn't match.
     * Make sure to set calling identity properly before calling.
     */
    private void requireOwnershipForItem(@Nullable String itemOwner, Uri item) {
        final boolean hasOwner = (itemOwner != null);
        final boolean callerIsOwner = Objects.equals(getCallingPackageOrSelf(), itemOwner);
        if (hasOwner && !callerIsOwner) {
            throw new IllegalStateException(
                    "Only owner is able to interact with pending/trashed item " + item);
        }
    }

    private ParcelFileDescriptor openWithFuse(String filePath, int uid, int mediaCapabilitiesUid,
            int modeBits, boolean shouldRedact, boolean shouldTranscode, int transcodeReason)
            throws FileNotFoundException {
        Log.d(TAG, "Open with FUSE. FilePath: " + filePath
                + ". Uid: " + uid
                + ". Media Capabilities Uid: " + mediaCapabilitiesUid
                + ". ShouldRedact: " + shouldRedact
                + ". ShouldTranscode: " + shouldTranscode);

        int tid = android.os.Process.myTid();
        synchronized (mPendingOpenInfo) {
            mPendingOpenInfo.put(tid,
                    new PendingOpenInfo(uid, mediaCapabilitiesUid, shouldRedact, transcodeReason));
        }

        try {
            return FileUtils.openSafely(toFuseFile(new File(filePath)), modeBits);
        } finally {
            synchronized (mPendingOpenInfo) {
                mPendingOpenInfo.remove(tid);
            }
        }
    }

    private @NonNull FuseDaemon getFuseDaemonForFile(@NonNull File file)
            throws FileNotFoundException {
        final FuseDaemon daemon = ExternalStorageServiceImpl.getFuseDaemon(getVolumeId(file));
        if (daemon == null) {
            throw new FileNotFoundException("Missing FUSE daemon for " + file);
        } else {
            return daemon;
        }
    }

    private void invalidateFuseDentry(@NonNull File file) {
        invalidateFuseDentry(file.getAbsolutePath());
    }

    private void invalidateFuseDentry(@NonNull String path) {
        try {
            final FuseDaemon daemon = getFuseDaemonForFile(new File(path));
            if (isFuseThread()) {
                // If we are on a FUSE thread, we don't need to invalidate,
                // (and *must* not, otherwise we'd crash) because the invalidation
                // is already reflected in the lower filesystem
                return;
            } else {
                daemon.invalidateFuseDentryCache(path);
            }
        } catch (FileNotFoundException e) {
            Log.w(TAG, "Failed to invalidate FUSE dentry", e);
        }
    }

    /**
     * Replacement for {@link #openFileHelper(Uri, String)} which enforces any
     * permissions applicable to the path before returning.
     *
     * <p>This function should never be called from the fuse thread since it tries to open
     * a "/mnt/user" path.
     */
    private ParcelFileDescriptor openFileAndEnforcePathPermissionsHelper(Uri uri, int match,
            String mode, CancellationSignal signal, @NonNull Bundle opts)
            throws FileNotFoundException {
        int modeBits = ParcelFileDescriptor.parseMode(mode);
        boolean forWrite = (modeBits & ParcelFileDescriptor.MODE_WRITE_ONLY) != 0;
        final Uri redactedUri = opts.getParcelable(QUERY_ARG_REDACTED_URI);
        if (forWrite) {
            if (redactedUri != null) {
                throw new UnsupportedOperationException(
                        "Write is not supported on " + redactedUri.toString());
            }
            // Upgrade 'w' only to 'rw'. This allows us acquire a WR_LOCK when calling
            // #shouldOpenWithFuse
            modeBits |= ParcelFileDescriptor.MODE_READ_WRITE;
        }

        final boolean hasOwnerPackageName = hasOwnerPackageName(uri);
        final String[] projection = new String[] {
                MediaColumns.DATA,
                hasOwnerPackageName ? MediaColumns.OWNER_PACKAGE_NAME : "NULL",
                hasOwnerPackageName ? MediaColumns.IS_PENDING : "0",
        };

        final File file;
        final String ownerPackageName;
        final boolean isPending;
        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try (Cursor c = queryForSingleItem(uri, projection, null, null, signal)) {
            final String data = c.getString(0);
            if (TextUtils.isEmpty(data)) {
                throw new FileNotFoundException("Missing path for " + uri);
            } else {
                file = new File(data).getCanonicalFile();
            }
            ownerPackageName = c.getString(1);
            isPending = c.getInt(2) != 0;
        } catch (IOException e) {
            throw new FileNotFoundException(e.toString());
        } finally {
            restoreLocalCallingIdentity(token);
        }

        if (redactedUri == null) {
            checkAccess(uri, Bundle.EMPTY, file, forWrite);
        } else {
            checkAccess(redactedUri, Bundle.EMPTY, file, false);
        }

        // We don't check ownership for files with IS_PENDING set by FUSE
        if (isPending && !isPendingFromFuse(file)) {
            requireOwnershipForItem(ownerPackageName, uri);
        }

        final boolean callerIsOwner = Objects.equals(getCallingPackageOrSelf(), ownerPackageName);
        // Figure out if we need to redact contents
        final boolean redactionNeeded =
                (redactedUri != null) || (!callerIsOwner && isRedactionNeeded(uri));
        final RedactionInfo redactionInfo;
        try {
            redactionInfo = redactionNeeded ? getRedactionRanges(file)
                    : new RedactionInfo(new long[0], new long[0]);
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }

        // Yell if caller requires original, since we can't give it to them
        // unless they have access granted above
        if (redactionNeeded && MediaStore.getRequireOriginal(uri)) {
            throw new UnsupportedOperationException(
                    "Caller must hold ACCESS_MEDIA_LOCATION permission to access original");
        }

        // Kick off metadata update when writing is finished
        final OnCloseListener listener = (e) -> {
            // We always update metadata to reflect the state on disk, even when
            // the remote writer tried claiming an exception
            invalidateThumbnails(uri);

            // Invalidate so subsequent stat(2) on the upper fs is eventually consistent
            invalidateFuseDentry(file);
            try {
                switch (match) {
                    case IMAGES_THUMBNAILS_ID:
                    case VIDEO_THUMBNAILS_ID:
                        final ContentValues values = new ContentValues();
                        updateImageMetadata(values, file);
                        update(uri, values, null, null);
                        break;
                    default:
                        scanFileAsMediaProvider(file, REASON_DEMAND);
                        break;
                }
            } catch (Exception e2) {
                Log.w(TAG, "Failed to update metadata for " + uri, e2);
            }
        };

        try {
            // First, handle any redaction that is needed for caller
            final ParcelFileDescriptor pfd;
            final String filePath = file.getPath();
            final int uid = Binder.getCallingUid();
            final int transcodeReason = mTranscodeHelper.shouldTranscode(filePath, uid, opts);
            final boolean shouldTranscode = transcodeReason > 0;
            int mediaCapabilitiesUid = opts.getInt(MediaStore.EXTRA_MEDIA_CAPABILITIES_UID);
            if (!shouldTranscode || mediaCapabilitiesUid < Process.FIRST_APPLICATION_UID) {
                // Although 0 is a valid UID, it's not a valid app uid.
                // So, we use it to signify that mediaCapabilitiesUid is not set.
                mediaCapabilitiesUid = 0;
            }
            if (redactionInfo.redactionRanges.length > 0) {
                // If fuse is enabled, we can provide an fd that points to the fuse
                // file system and handle redaction in the fuse handler when the caller reads.
                pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
                        true /* shouldRedact */, shouldTranscode, transcodeReason);
            } else if (shouldTranscode) {
                pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
                        false /* shouldRedact */, shouldTranscode, transcodeReason);
            } else {
                FuseDaemon daemon = null;
                try {
                    daemon = getFuseDaemonForFile(file);
                } catch (FileNotFoundException ignored) {
                }
                ParcelFileDescriptor lowerFsFd = FileUtils.openSafely(file, modeBits);
                // Always acquire a readLock. This allows us make multiple opens via lower
                // filesystem
                boolean shouldOpenWithFuse = daemon != null
                        && daemon.shouldOpenWithFuse(filePath, true /* forRead */,
                        lowerFsFd.getFd());

                if (shouldOpenWithFuse) {
                    // If the file is already opened on the FUSE mount with VFS caching enabled
                    // we return an upper filesystem fd (via FUSE) to avoid file corruption
                    // resulting from cache inconsistencies between the upper and lower
                    // filesystem caches
                    pfd = openWithFuse(filePath, uid, mediaCapabilitiesUid, modeBits,
                            false /* shouldRedact */, shouldTranscode, transcodeReason);
                    try {
                        lowerFsFd.close();
                    } catch (IOException e) {
                        Log.w(TAG, "Failed to close lower filesystem fd " + file.getPath(), e);
                    }
                } else {
                    Log.i(TAG, "Open with lower FS for " + filePath + ". Uid: " + uid);
                    if (forWrite) {
                        // When opening for write on the lower filesystem, invalidate the VFS dentry
                        // so subsequent open/getattr calls will return correctly.
                        //
                        // A 'dirty' dentry with write back cache enabled can cause the kernel to
                        // ignore file attributes or even see stale page cache data when the lower
                        // filesystem has been modified outside of the FUSE driver
                        invalidateFuseDentry(file);
                    }

                    pfd = lowerFsFd;
                }
            }

            // Second, wrap in any listener that we've requested
            if (!isPending && forWrite && listener != null) {
                return ParcelFileDescriptor.wrap(pfd, BackgroundThread.getHandler(), listener);
            } else {
                return pfd;
            }
        } catch (IOException e) {
            if (e instanceof FileNotFoundException) {
                throw (FileNotFoundException) e;
            } else {
                throw new IllegalStateException(e);
            }
        }
    }

    private void deleteAndInvalidate(@NonNull Path path) {
        deleteAndInvalidate(path.toFile());
    }

    private void deleteAndInvalidate(@NonNull File file) {
        file.delete();
        invalidateFuseDentry(file);
    }

    private void deleteIfAllowed(Uri uri, Bundle extras, String path) {
        try {
            final File file = new File(path).getCanonicalFile();
            checkAccess(uri, extras, file, true);
            deleteAndInvalidate(file);
        } catch (Exception e) {
            Log.e(TAG, "Couldn't delete " + path, e);
        }
    }

    @Deprecated
    private boolean isPending(Uri uri) {
        final int match = matchUri(uri, true);
        switch (match) {
            case AUDIO_MEDIA_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
                try (Cursor c = queryForSingleItem(uri,
                        new String[] { MediaColumns.IS_PENDING }, null, null, null)) {
                    return (c.getInt(0) != 0);
                } catch (FileNotFoundException e) {
                    throw new IllegalStateException(e);
                }
            default:
                return false;
        }
    }

    @Deprecated
    private boolean isRedactionNeeded(Uri uri) {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_REDACTION_NEEDED);
    }

    private boolean isRedactionNeeded() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_REDACTION_NEEDED);
    }

    private boolean isCallingPackageRequestingLegacy() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_LEGACY_GRANTED);
    }

    private boolean shouldBypassDatabase(int uid) {
        if (uid != android.os.Process.SHELL_UID && isCallingPackageManager()) {
            return mCallingIdentity.get().shouldBypassDatabase(false /*isSystemGallery*/);
        } else if (isCallingPackageSystemGallery()) {
            if (isCallingPackageLegacyWrite()) {
                // We bypass db operations for legacy system galleries with W_E_S (see b/167307393).
                // Tracking a longer term solution in b/168784136.
                return true;
            } else if (isCallingPackageRequestingLegacy()) {
                // If requesting legacy, app should have W_E_S along with SystemGallery appops.
                return false;
            } else if (!SdkLevel.isAtLeastS()) {
                // We don't parse manifest flags for SdkLevel<=R yet. Hence, we don't bypass
                // database updates for SystemGallery targeting R or above on R OS.
                return false;
            }
            return mCallingIdentity.get().shouldBypassDatabase(true /*isSystemGallery*/);
        }
        return false;
    }

    private static int getFileMediaType(String path) {
        final File file = new File(path);
        final String mimeType = MimeUtils.resolveMimeType(file);
        return MimeUtils.resolveMediaType(mimeType);
    }

    private boolean canAccessMediaFile(String filePath, boolean excludeNonSystemGallery) {
        if (excludeNonSystemGallery && !isCallingPackageSystemGallery()) {
            return false;
        }
        switch (getFileMediaType(filePath)) {
            case FileColumns.MEDIA_TYPE_IMAGE:
                return mCallingIdentity.get().hasPermission(PERMISSION_WRITE_IMAGES);
            case FileColumns.MEDIA_TYPE_VIDEO:
                return mCallingIdentity.get().hasPermission(PERMISSION_WRITE_VIDEO);
            default:
                return false;
        }
    }

    /**
     * Returns true if:
     * <ul>
     * <li>the calling identity is an app targeting Q or older versions AND is requesting legacy
     * storage
     * <li>the calling identity holds {@code MANAGE_EXTERNAL_STORAGE}
     * <li>the calling identity owns or has access to the filePath (eg /Android/data/com.foo)
     * <li>the calling identity has permission to write images and the given file is an image file
     * <li>the calling identity has permission to write video and the given file is an video file
     * </ul>
     */
    private boolean shouldBypassFuseRestrictions(boolean forWrite, String filePath) {
        boolean isRequestingLegacyStorage = forWrite ? isCallingPackageLegacyWrite()
                : isCallingPackageLegacyRead();
        if (isRequestingLegacyStorage) {
            return true;
        }

        if (isCallingPackageManager()) {
            return true;
        }

        // Check if the caller has access to private app directories.
        if (isUidAllowedAccessToDataOrObbPathForFuse(mCallingIdentity.get().uid, filePath)) {
            return true;
        }

        // Apps with write access to images and/or videos can bypass our restrictions if all of the
        // the files they're accessing are of the compatible media type.
        if (canAccessMediaFile(filePath, /*excludeNonSystemGallery*/ false)) {
            return true;
        }

        return false;
    }

    /**
     * Returns true if the passed in path is an application-private data directory
     * (such as Android/data/com.foo or Android/obb/com.foo) that does not belong to the caller and
     * the caller does not have special access.
     */
    private boolean isPrivatePackagePathNotAccessibleByCaller(String path) {
        // Files under the apps own private directory
        final String appSpecificDir = extractPathOwnerPackageName(path);

        if (appSpecificDir == null) {
            return false;
        }

        // Android/media is not considered private, because it contains media that is explicitly
        // scanned and shared by other apps
        if (isExternalMediaDirectory(path)) {
            return false;
        }
        return !isUidAllowedAccessToDataOrObbPathForFuse(mCallingIdentity.get().uid, path);
    }

    private boolean shouldBypassDatabaseAndSetDirtyForFuse(int uid, String path) {
        if (shouldBypassDatabase(uid)) {
            synchronized (mNonHiddenPaths) {
                File file = new File(path);
                String key = file.getParent();
                boolean maybeHidden = !mNonHiddenPaths.containsKey(key);

                if (maybeHidden) {
                    File topNoMediaDir = FileUtils.getTopLevelNoMedia(new File(path));
                    if (topNoMediaDir == null) {
                        mNonHiddenPaths.put(key, 0);
                    } else {
                        mMediaScanner.onDirectoryDirty(topNoMediaDir);
                    }
                }
            }
            return true;
        }
        return false;
    }

    /**
     * Set of Exif tags that should be considered for redaction.
     */
    private static final String[] REDACTED_EXIF_TAGS = new String[] {
            ExifInterface.TAG_GPS_ALTITUDE,
            ExifInterface.TAG_GPS_ALTITUDE_REF,
            ExifInterface.TAG_GPS_AREA_INFORMATION,
            ExifInterface.TAG_GPS_DOP,
            ExifInterface.TAG_GPS_DATESTAMP,
            ExifInterface.TAG_GPS_DEST_BEARING,
            ExifInterface.TAG_GPS_DEST_BEARING_REF,
            ExifInterface.TAG_GPS_DEST_DISTANCE,
            ExifInterface.TAG_GPS_DEST_DISTANCE_REF,
            ExifInterface.TAG_GPS_DEST_LATITUDE,
            ExifInterface.TAG_GPS_DEST_LATITUDE_REF,
            ExifInterface.TAG_GPS_DEST_LONGITUDE,
            ExifInterface.TAG_GPS_DEST_LONGITUDE_REF,
            ExifInterface.TAG_GPS_DIFFERENTIAL,
            ExifInterface.TAG_GPS_IMG_DIRECTION,
            ExifInterface.TAG_GPS_IMG_DIRECTION_REF,
            ExifInterface.TAG_GPS_LATITUDE,
            ExifInterface.TAG_GPS_LATITUDE_REF,
            ExifInterface.TAG_GPS_LONGITUDE,
            ExifInterface.TAG_GPS_LONGITUDE_REF,
            ExifInterface.TAG_GPS_MAP_DATUM,
            ExifInterface.TAG_GPS_MEASURE_MODE,
            ExifInterface.TAG_GPS_PROCESSING_METHOD,
            ExifInterface.TAG_GPS_SATELLITES,
            ExifInterface.TAG_GPS_SPEED,
            ExifInterface.TAG_GPS_SPEED_REF,
            ExifInterface.TAG_GPS_STATUS,
            ExifInterface.TAG_GPS_TIMESTAMP,
            ExifInterface.TAG_GPS_TRACK,
            ExifInterface.TAG_GPS_TRACK_REF,
            ExifInterface.TAG_GPS_VERSION_ID,
    };

    /**
     * Set of ISO boxes that should be considered for redaction.
     */
    private static final int[] REDACTED_ISO_BOXES = new int[] {
            IsoInterface.BOX_LOCI,
            IsoInterface.BOX_XYZ,
            IsoInterface.BOX_GPS,
            IsoInterface.BOX_GPS0,
    };

    public static final Set<String> sRedactedExifTags = new ArraySet<>(
            Arrays.asList(REDACTED_EXIF_TAGS));

    private static final class RedactionInfo {
        public final long[] redactionRanges;
        public final long[] freeOffsets;

        public RedactionInfo() {
            this.redactionRanges = new long[0];
            this.freeOffsets = new long[0];
        }

        public RedactionInfo(long[] redactionRanges, long[] freeOffsets) {
            this.redactionRanges = redactionRanges;
            this.freeOffsets = freeOffsets;
        }
    }

    private static class LRUCache<K, V> extends LinkedHashMap<K, V> {
        private final int mMaxSize;

        public LRUCache(int maxSize) {
            this.mMaxSize = maxSize;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > mMaxSize;
        }
    }

    private static final class PendingOpenInfo {
        public final int uid;
        public final int mediaCapabilitiesUid;
        public final boolean shouldRedact;
        public final int transcodeReason;

        public PendingOpenInfo(int uid, int mediaCapabilitiesUid, boolean shouldRedact,
                int transcodeReason) {
            this.uid = uid;
            this.mediaCapabilitiesUid = mediaCapabilitiesUid;
            this.shouldRedact = shouldRedact;
            this.transcodeReason = transcodeReason;
        }
    }

    /**
     * Calculates the ranges that need to be redacted for the given file and user that wants to
     * access the file.
     * Note: This method assumes that the caller of this function has already done permission checks
     * for the uid to access this path.
     *
     * @param uid UID of the package wanting to access the file
     * @param path File path
     * @param tid thread id making IO on the FUSE filesystem
     * @return Ranges that should be redacted.
     *
     * @throws IOException if an error occurs while calculating the redaction ranges
     */
    @NonNull
    private long[] getRedactionRangesForFuse(String path, String ioPath, int original_uid, int uid,
            int tid, boolean forceRedaction) throws IOException {
        // |ioPath| might refer to a transcoded file path (which is not indexed in the db)
        // |path| will always refer to a valid _data column
        // We use |ioPath| for the filesystem access because in the case of transcoding,
        // we want to get redaction ranges from the transcoded file and *not* the original file
        final File file = new File(ioPath);

        if (forceRedaction) {
            return getRedactionRanges(file).redactionRanges;
        }

        // When calculating redaction ranges initiated from MediaProvider, the redaction policy
        // is slightly different from the FUSE initiated opens redaction policy. targetSdk=29 from
        // MediaProvider requires redaction, but targetSdk=29 apps from FUSE don't require redaction
        // Hence, we check the mPendingOpenInfo object (populated when opens are initiated from
        // MediaProvider) if there's a pending open from MediaProvider with matching tid and uid and
        // use the shouldRedact decision there if there's one.
        synchronized (mPendingOpenInfo) {
            PendingOpenInfo info = mPendingOpenInfo.get(tid);
            if (info != null && info.uid == original_uid) {
                boolean shouldRedact = info.shouldRedact;
                if (shouldRedact) {
                    return getRedactionRanges(file).redactionRanges;
                } else {
                    return new long[0];
                }
            }
        }

        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        try {
            if (!isRedactionNeeded()
                    || shouldBypassFuseRestrictions(/*forWrite*/ false, path)) {
                return new long[0];
            }

            final Uri contentUri = FileUtils.getContentUriForPath(path);
            final String[] projection = new String[]{
                    MediaColumns.OWNER_PACKAGE_NAME, MediaColumns._ID , FileColumns.MEDIA_TYPE};
            final String selection = MediaColumns.DATA + "=?";
            final String[] selectionArgs = new String[]{path};
            final String ownerPackageName;
            final int id;
            final int mediaType;
            // Query as MediaProvider as non-RES apps will result in FileNotFoundException.
            // Note: The caller uid already has passed permission checks to access this file.
            try (final Cursor c = queryForSingleItemAsMediaProvider(contentUri, projection,
                    selection, selectionArgs, null)) {
                c.moveToFirst();
                ownerPackageName = c.getString(0);
                id = c.getInt(1);
                mediaType = c.getInt(2);
            } catch (FileNotFoundException e) {
                // Ideally, this shouldn't happen unless the file was deleted after we checked its
                // existence and before we get to the redaction logic here. In this case we throw
                // and fail the operation and FuseDaemon should handle this and fail the whole open
                // operation gracefully.
                throw new FileNotFoundException(
                        path + " not found while calculating redaction ranges: " + e.getMessage());
            }

            final boolean callerIsOwner = Objects.equals(getCallingPackageOrSelf(),
                    ownerPackageName);

            // Do not redact if the caller is the owner
            if (callerIsOwner) {
                return new long[0];
            }

            // Do not redact if the caller has write uri permission granted on the file.
            final Uri fileUri = ContentUris.withAppendedId(contentUri, id);
            boolean callerHasWriteUriPermission = getContext().checkUriPermission(
                    fileUri, mCallingIdentity.get().pid, mCallingIdentity.get().uid,
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == PERMISSION_GRANTED;
            if (callerHasWriteUriPermission) {
                return new long[0];
            }
            // Check if the caller has write access to other uri formats for the same file.
            callerHasWriteUriPermission = getOtherUriGrantsForPath(path, mediaType,
                    Long.toString(id), /* forWrite */ true) != null;
            if (callerHasWriteUriPermission) {
                return new long[0];
            }

            return getRedactionRanges(file).redactionRanges;
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    /**
     * Calculates the ranges containing sensitive metadata that should be redacted if the caller
     * doesn't have the required permissions.
     *
     * @param file file to be redacted
     * @return the ranges to be redacted in a RedactionInfo object, could be empty redaction ranges
     * if there's sensitive metadata
     * @throws IOException if an IOException happens while calculating the redaction ranges
     */
    @VisibleForTesting
    public static RedactionInfo getRedactionRanges(File file) throws IOException {
        try (FileInputStream is = new FileInputStream(file)) {
            return getRedactionRanges(is, MimeUtils.resolveMimeType(file));
        } catch (FileNotFoundException ignored) {
            // If file not found, then there's nothing to redact
            return new RedactionInfo();
        } catch (IOException e) {
            throw new IOException("Failed to redact " + file, e);
        }
    }

    /**
     * Calculates the ranges containing sensitive metadata that should be redacted if the caller
     * doesn't have the required permissions.
     *
     * @param fis {@link FileInputStream} to be redacted
     * @return the ranges to be redacted in a RedactionInfo object, could be empty redaction ranges
     * if there's sensitive metadata
     * @throws IOException if an IOException happens while calculating the redaction ranges
     */
    @VisibleForTesting
    public static RedactionInfo getRedactionRanges(FileInputStream fis, String mimeType)
            throws IOException {
        final LongArray res = new LongArray();
        final LongArray freeOffsets = new LongArray();

        Trace.beginSection("getRedactionRanges");
        try {
            if (ExifInterface.isSupportedMimeType(mimeType)) {
                final ExifInterface exif = new ExifInterface(fis.getFD());
                for (String tag : REDACTED_EXIF_TAGS) {
                    final long[] range = exif.getAttributeRange(tag);
                    if (range != null) {
                        res.add(range[0]);
                        res.add(range[0] + range[1]);
                    }
                }
                // Redact xmp where present
                final XmpInterface exifXmp = XmpInterface.fromContainer(exif);
                res.addAll(exifXmp.getRedactionRanges());
            }

            if (IsoInterface.isSupportedMimeType(mimeType)) {
                final IsoInterface iso = IsoInterface.fromFileDescriptor(fis.getFD());
                for (int box : REDACTED_ISO_BOXES) {
                    final long[] ranges = iso.getBoxRanges(box);
                    for (int i = 0; i < ranges.length; i += 2) {
                        long boxTypeOffset = ranges[i] - 4;
                        freeOffsets.add(boxTypeOffset);
                        res.add(boxTypeOffset);
                        res.add(ranges[i + 1]);
                    }
                }
                // Redact xmp where present
                final XmpInterface isoXmp = XmpInterface.fromContainer(iso);
                res.addAll(isoXmp.getRedactionRanges());
            }

            return new RedactionInfo(res.toArray(), freeOffsets.toArray());
        } finally {
            Trace.endSection();
        }
    }

    /**
     * @return {@code true} if {@code file} is pending from FUSE, {@code false} otherwise.
     * Files pending from FUSE will not have pending file pattern.
     */
    private static boolean isPendingFromFuse(@NonNull File file) {
        final Matcher matcher =
                FileUtils.PATTERN_EXPIRES_FILE.matcher(extractDisplayName(file.getName()));
        return !matcher.matches();
    }

    private FileAccessAttributes queryForFileAttributes(final String path)
            throws FileNotFoundException {
        Trace.beginSection("queryFileAttr");
        final Uri contentUri = FileUtils.getContentUriForPath(path);
        final String[] projection = new String[]{
                MediaColumns._ID,
                MediaColumns.OWNER_PACKAGE_NAME,
                MediaColumns.IS_PENDING,
                FileColumns.MEDIA_TYPE,
                MediaColumns.IS_TRASHED
        };
        final String selection = MediaColumns.DATA + "=?";
        final String[] selectionArgs = new String[]{path};
        FileAccessAttributes fileAccessAttributes;
        try (final Cursor c = queryForSingleItemAsMediaProvider(contentUri, projection,
                selection,
                selectionArgs, null)) {
            fileAccessAttributes = FileAccessAttributes.fromCursor(c);
        }
        Trace.endSection();
        return fileAccessAttributes;
    }

    private void checkIfFileOpenIsPermitted(String path,
            FileAccessAttributes fileAccessAttributes, String redactedUriId,
            boolean forWrite) throws FileNotFoundException {
        final File file = new File(path);
        Uri fileUri = MediaStore.Files.getContentUri(extractVolumeName(path),
                fileAccessAttributes.getId());
        // We don't check ownership for files with IS_PENDING set by FUSE
        // Please note that even if ownerPackageName is null, the check below will throw an
        // IllegalStateException
        if (fileAccessAttributes.isTrashed() || (fileAccessAttributes.isPending()
                && !isPendingFromFuse(new File(path)))) {
            requireOwnershipForItem(fileAccessAttributes.getOwnerPackageName(), fileUri);
        }

        // Check that path looks consistent before uri checks
        if (!FileUtils.contains(Environment.getStorageDirectory(), file)) {
            checkWorldReadAccess(file.getAbsolutePath());
        }

        try {
            // checkAccess throws FileNotFoundException only from checkWorldReadAccess(),
            // which we already check above. Hence, handling only SecurityException.
            if (redactedUriId != null) {
                fileUri = ContentUris.removeId(fileUri).buildUpon().appendPath(
                        redactedUriId).build();
            }
            checkAccess(fileUri, Bundle.EMPTY, file, forWrite);
        } catch (SecurityException e) {
            // Check for other Uri formats only when the single uri check flow fails.
            // Throw the previous exception if the multi-uri checks failed.
            final String uriId = redactedUriId == null
                    ? Long.toString(fileAccessAttributes.getId()) : redactedUriId;
            if (getOtherUriGrantsForPath(path, fileAccessAttributes.getMediaType(),
                    uriId, forWrite) == null) {
                throw e;
            }
        }
    }


    /**
     * Checks if the app identified by the given UID is allowed to open the given file for the given
     * access mode.
     *
     * @param path the path of the file to be opened
     * @param uid UID of the app requesting to open the file
     * @param forWrite specifies if the file is to be opened for write
     * @return {@link FileOpenResult} with {@code status} {@code 0} upon success and
     * {@link FileOpenResult} with {@code status} {@link OsConstants#EACCES} if the operation is
     * illegal or not permitted for the given {@code uid} or if the calling package is a legacy app
     * that doesn't have right storage permission.
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public FileOpenResult onFileOpenForFuse(String path, String ioPath, int uid, int tid,
            int transformsReason, boolean forWrite, boolean redact, boolean logTransformsMetrics) {
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));

        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), path);

        boolean isSuccess = false;

        final int originalUid = getBinderUidForFuse(uid, tid);
        final int callingUserId = uidToUserId(uid);
        int mediaCapabilitiesUid = 0;
        final PendingOpenInfo pendingOpenInfo;
        synchronized (mPendingOpenInfo) {
            pendingOpenInfo = mPendingOpenInfo.get(tid);
        }

        if (pendingOpenInfo != null && pendingOpenInfo.uid == originalUid) {
            mediaCapabilitiesUid = pendingOpenInfo.mediaCapabilitiesUid;
        }

        try {
            boolean forceRedaction = false;
            String redactedUriId = null;
            if (isSyntheticPath(path, callingUserId)) {
                if (forWrite) {
                    // Synthetic URIs are not allowed to update EXIF headers.
                    return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
                            mediaCapabilitiesUid, new long[0]);
                }

                if (isRedactedPath(path, callingUserId)) {
                    redactedUriId = extractFileName(path);

                    // If path is redacted Uris' path, ioPath must be the real path, ioPath must
                    // haven been updated to the real path during onFileLookupForFuse.
                    path = ioPath;

                    // Irrespective of the permissions we want to redact in this case.
                    redact = true;
                    forceRedaction = true;
                } else if (isPickerPath(path, callingUserId)) {
                    return handlePickerFileOpen(path, originalUid);
                } else {
                    // we don't support any other transformations under .transforms/synthetic dir
                    return new FileOpenResult(OsConstants.ENOENT /* status */, originalUid,
                            mediaCapabilitiesUid, new long[0]);
                }
            }

            if (isPrivatePackagePathNotAccessibleByCaller(path)) {
                Log.e(TAG, "Can't open a file in another app's external directory!");
                return new FileOpenResult(OsConstants.ENOENT, originalUid, mediaCapabilitiesUid,
                        new long[0]);
            }

            if (shouldBypassFuseRestrictions(forWrite, path)) {
                isSuccess = true;
                return new FileOpenResult(0 /* status */, originalUid, mediaCapabilitiesUid,
                        redact ? getRedactionRangesForFuse(path, ioPath, originalUid, uid, tid,
                                forceRedaction) : new long[0]);
            }
            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (isCallingPackageRequestingLegacy()) {
                return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
                        mediaCapabilitiesUid, new long[0]);
            }
            // TODO: Fetch owner id from Android/media directory and check if caller is owner
            FileAccessAttributes fileAttributes = null;
            if (XAttrUtils.ENABLE_XATTR_METADATA_FOR_FUSE) {
                Optional<FileAccessAttributes> fileAttributesThroughXattr =
                        XAttrUtils.getFileAttributesFromXAttr(path,
                                XAttrUtils.FILE_ACCESS_XATTR_KEY);
                if (fileAttributesThroughXattr.isPresent()) {
                    fileAttributes = fileAttributesThroughXattr.get();
                }
            }

            // FileAttributes will be null if the xattr call failed or the flag to enable xattr
            // metadata support is not set
            if (fileAttributes == null)  {
                fileAttributes = queryForFileAttributes(path);
            }
            checkIfFileOpenIsPermitted(path, fileAttributes, redactedUriId, forWrite);
            isSuccess = true;
            return new FileOpenResult(0 /* status */, originalUid, mediaCapabilitiesUid,
                    redact ? getRedactionRangesForFuse(path, ioPath, originalUid, uid, tid,
                            forceRedaction) : new long[0]);
        } catch (IOException e) {
            // We are here because
            // * There is no db row corresponding to the requested path, which is more unlikely.
            // * getRedactionRangesForFuse couldn't fetch the redaction info correctly
            // In all of these cases, it means that app doesn't have access permission to the file.
            Log.e(TAG, "Couldn't find file: " + path, e);
            return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
                    mediaCapabilitiesUid, new long[0]);
        } catch (IllegalStateException | SecurityException e) {
            Log.e(TAG, "Permission to access file: " + path + " is denied");
            return new FileOpenResult(OsConstants.EACCES /* status */, originalUid,
                    mediaCapabilitiesUid, new long[0]);
        } finally {
            if (isSuccess && logTransformsMetrics) {
                notifyTranscodeHelperOnFileOpen(path, ioPath, originalUid, transformsReason);
            }
            restoreLocalCallingIdentity(token);
        }
    }

    private @Nullable Uri getOtherUriGrantsForPath(String path, boolean forWrite) {
        final Uri contentUri = FileUtils.getContentUriForPath(path);
        final String[] projection = new String[]{
                MediaColumns._ID,
                FileColumns.MEDIA_TYPE};
        final String selection = MediaColumns.DATA + "=?";
        final String[] selectionArgs = new String[]{path};
        final String id;
        final int mediaType;
        try (final Cursor c = queryForSingleItemAsMediaProvider(contentUri, projection, selection,
                selectionArgs, null)) {
            id = c.getString(0);
            mediaType = c.getInt(1);
            return getOtherUriGrantsForPath(path, mediaType, id, forWrite);
        } catch (FileNotFoundException ignored) {
        }
        return null;
    }

    @Nullable
    private Uri getOtherUriGrantsForPath(String path, int mediaType, String id, boolean forWrite) {
        List<Uri> otherUris = new ArrayList<Uri>();
        final Uri mediaUri = getMediaUriForFuse(extractVolumeName(path), mediaType, id);
        otherUris.add(mediaUri);
        final Uri externalMediaUri = getMediaUriForFuse(MediaStore.VOLUME_EXTERNAL, mediaType, id);
        otherUris.add(externalMediaUri);
        return getPermissionGrantedUri(otherUris, forWrite);
    }

    @NonNull
    private Uri getMediaUriForFuse(@NonNull String volumeName, int mediaType, String id) {
        Uri uri = MediaStore.Files.getContentUri(volumeName);
        switch (mediaType) {
            case FileColumns.MEDIA_TYPE_IMAGE:
                uri = MediaStore.Images.Media.getContentUri(volumeName);
                break;
            case FileColumns.MEDIA_TYPE_VIDEO:
                uri = MediaStore.Video.Media.getContentUri(volumeName);
                break;
            case FileColumns.MEDIA_TYPE_AUDIO:
                uri = MediaStore.Audio.Media.getContentUri(volumeName);
                break;
            case FileColumns.MEDIA_TYPE_PLAYLIST:
                uri = MediaStore.Audio.Playlists.getContentUri(volumeName);
                break;
        }

        return uri.buildUpon().appendPath(id).build();
    }

    /**
     * Returns {@code true} if {@link #mCallingIdentity#getSharedPackages(String)} contains the
     * given package name, {@code false} otherwise.
     * <p> Assumes that {@code mCallingIdentity} has been properly set to reflect the calling
     * package.
     */
    private boolean isCallingIdentitySharedPackageName(@NonNull String packageName) {
        for (String sharedPkgName : mCallingIdentity.get().getSharedPackageNames()) {
            if (packageName.toLowerCase(Locale.ROOT)
                    .equals(sharedPkgName.toLowerCase(Locale.ROOT))) {
                return true;
            }
        }
        return false;
    }

    /**
     * @throws IllegalStateException if path is invalid or doesn't match a volume.
     */
    @NonNull
    private Uri getContentUriForFile(@NonNull String filePath, @NonNull String mimeType) {
        final String volName;
        try {
            volName = FileUtils.getVolumeName(getContext(), new File(filePath));
        } catch (FileNotFoundException e) {
            throw new IllegalStateException("Couldn't get volume name for " + filePath);
        }
        Uri uri = Files.getContentUri(volName);
        String topLevelDir = extractTopLevelDir(filePath);
        if (topLevelDir == null) {
            // If the file path doesn't match the external storage directory, we use the files URI
            // as default and let #insert enforce the restrictions
            return uri;
        }
        topLevelDir = topLevelDir.toLowerCase(Locale.ROOT);

        switch (topLevelDir) {
            case DIRECTORY_PODCASTS_LOWER_CASE:
            case DIRECTORY_RINGTONES_LOWER_CASE:
            case DIRECTORY_ALARMS_LOWER_CASE:
            case DIRECTORY_NOTIFICATIONS_LOWER_CASE:
            case DIRECTORY_AUDIOBOOKS_LOWER_CASE:
            case DIRECTORY_RECORDINGS_LOWER_CASE:
                uri = Audio.Media.getContentUri(volName);
                break;
            case DIRECTORY_MUSIC_LOWER_CASE:
                if (MimeUtils.isPlaylistMimeType(mimeType)) {
                    uri = Audio.Playlists.getContentUri(volName);
                } else if (!MimeUtils.isSubtitleMimeType(mimeType)) {
                    // Send Files uri for media type subtitle
                    uri = Audio.Media.getContentUri(volName);
                }
                break;
            case DIRECTORY_MOVIES_LOWER_CASE:
                if (MimeUtils.isPlaylistMimeType(mimeType)) {
                    uri = Audio.Playlists.getContentUri(volName);
                } else if (!MimeUtils.isSubtitleMimeType(mimeType)) {
                    // Send Files uri for media type subtitle
                    uri = Video.Media.getContentUri(volName);
                }
                break;
            case DIRECTORY_DCIM_LOWER_CASE:
            case DIRECTORY_PICTURES_LOWER_CASE:
                if (MimeUtils.isImageMimeType(mimeType)) {
                    uri = Images.Media.getContentUri(volName);
                } else {
                    uri = Video.Media.getContentUri(volName);
                }
                break;
            case DIRECTORY_DOWNLOADS_LOWER_CASE:
            case DIRECTORY_DOCUMENTS_LOWER_CASE:
                break;
            default:
                Log.w(TAG, "Forgot to handle a top level directory in getContentUriForFile?");
        }
        return uri;
    }

    private boolean containsIgnoreCase(@Nullable List<String> stringsList, @Nullable String item) {
        if (item == null || stringsList == null) return false;

        for (String current : stringsList) {
            if (item.equalsIgnoreCase(current)) return true;
        }
        return false;
    }

    private boolean fileExists(@NonNull String absolutePath) {
        // We don't care about specific columns in the match,
        // we just want to check IF there's a match
        final String[] projection = {};
        final String selection = FileColumns.DATA + " = ?";
        final String[] selectionArgs = {absolutePath};
        final Uri uri = FileUtils.getContentUriForPath(absolutePath);

        final LocalCallingIdentity token = clearLocalCallingIdentity();
        try {
            try (final Cursor c = query(uri, projection, selection, selectionArgs, null)) {
                // Shouldn't return null
                return c.getCount() > 0;
            }
        } finally {
            clearLocalCallingIdentity(token);
        }
    }

    private Uri insertFileForFuse(@NonNull String path, @NonNull Uri uri, @NonNull String mimeType,
            boolean useData) {
        ContentValues values = new ContentValues();
        values.put(FileColumns.OWNER_PACKAGE_NAME, getCallingPackageOrSelf());
        values.put(MediaColumns.MIME_TYPE, mimeType);
        values.put(FileColumns.IS_PENDING, 1);

        if (useData) {
            values.put(FileColumns.DATA, path);
        } else {
            values.put(FileColumns.VOLUME_NAME, extractVolumeName(path));
            values.put(FileColumns.RELATIVE_PATH, extractRelativePath(path));
            values.put(FileColumns.DISPLAY_NAME, extractDisplayName(path));
        }
        return insert(uri, values, Bundle.EMPTY);
    }

    /**
     * Enforces file creation restrictions (see return values) for the given file on behalf of the
     * app with the given {@code uid}. If the file is added to the shared storage, creates a
     * database entry for it.
     * <p> Does NOT create file.
     *
     * @param path the path of the file
     * @param uid UID of the app requesting to create the file
     * @return In case of success, 0. If the operation is illegal or not permitted, returns the
     * appropriate {@code errno} value:
     * <ul>
     * <li>{@link OsConstants#ENOENT} if the app tries to create file in other app's external dir
     * <li>{@link OsConstants#EEXIST} if the file already exists
     * <li>{@link OsConstants#EPERM} if the file type doesn't match the relative path, or if the
     * calling package is a legacy app that doesn't have WRITE_EXTERNAL_STORAGE permission.
     * <li>{@link OsConstants#EIO} in case of any other I/O exception
     * </ul>
     *
     * @throws IllegalStateException if given path is invalid.
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public int insertFileIfNecessaryForFuse(@NonNull String path, int uid) {
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), path);

        try {
            if (isPrivatePackagePathNotAccessibleByCaller(path)) {
                Log.e(TAG, "Can't create a file in another app's external directory");
                return OsConstants.ENOENT;
            }

            if (!path.equals(getAbsoluteSanitizedPath(path))) {
                Log.e(TAG, "File name contains invalid characters");
                return OsConstants.EPERM;
            }

            if (shouldBypassDatabaseAndSetDirtyForFuse(uid, path)) {
                if (path.endsWith("/.nomedia")) {
                    File parent = new File(path).getParentFile();
                    synchronized (mNonHiddenPaths) {
                        mNonHiddenPaths.keySet().removeIf(
                                k -> FileUtils.contains(parent, new File(k)));
                    }
                }
                return 0;
            }

            final String mimeType = MimeUtils.resolveMimeType(new File(path));

            if (shouldBypassFuseRestrictions(/*forWrite*/ true, path)) {
                final boolean callerRequestingLegacy = isCallingPackageRequestingLegacy();
                if (!fileExists(path)) {
                    // If app has already inserted the db row, inserting the row again might set
                    // IS_PENDING=1. We shouldn't overwrite existing entry as part of FUSE
                    // operation, hence, insert the db row only when it doesn't exist.
                    try {
                        insertFileForFuse(path, FileUtils.getContentUriForPath(path),
                                mimeType, /*useData*/ callerRequestingLegacy);
                    } catch (Exception ignored) {
                    }
                } else {
                    // Upon creating a file via FUSE, if a row matching the path already exists
                    // but a file doesn't exist on the filesystem, we transfer ownership to the
                    // app attempting to create the file. If we don't update ownership, then the
                    // app that inserted the original row may be able to observe the contents of
                    // written file even though they don't hold the right permissions to do so.
                    if (callerRequestingLegacy) {
                        final String owner = getCallingPackageOrSelf();
                        if (owner != null && !updateOwnerForPath(path, owner)) {
                            return OsConstants.EPERM;
                        }
                    }
                }

                return 0;
            }

            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (isCallingPackageRequestingLegacy()) {
                return OsConstants.EPERM;
            }

            if (fileExists(path)) {
                // If the file already exists in the db, we shouldn't allow the file creation.
                return OsConstants.EEXIST;
            }

            final Uri contentUri = getContentUriForFile(path, mimeType);
            final Uri item = insertFileForFuse(path, contentUri, mimeType, /*useData*/ false);
            if (item == null) {
                return OsConstants.EPERM;
            }
            return 0;
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "insertFileIfNecessary failed", e);
            return OsConstants.EPERM;
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    private boolean updateOwnerForPath(@NonNull String path, @NonNull String newOwner) {
        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(FileUtils.getContentUriForPath(path));
        } catch (VolumeNotFoundException e) {
            // Cannot happen, as this is a path that we already resolved.
            throw new AssertionError("Path must already be resolved", e);
        }

        ContentValues values = new ContentValues(1);
        values.put(FileColumns.OWNER_PACKAGE_NAME, newOwner);

        return helper.runWithoutTransaction((db) -> {
            return db.update("files", values, "_data=?", new String[] { path });
        }) == 1;
    }

    private static int deleteFileUnchecked(@NonNull String path) {
        final File toDelete = new File(path);
        if (toDelete.delete()) {
            return 0;
        } else {
            return OsConstants.ENOENT;
        }
    }

    /**
     * Deletes file with the given {@code path} on behalf of the app with the given {@code uid}.
     * <p>Before deleting, checks if app has permissions to delete this file.
     *
     * @param path the path of the file
     * @param uid UID of the app requesting to delete the file
     * @return 0 upon success.
     * In case of error, return the appropriate negated {@code errno} value:
     * <ul>
     * <li>{@link OsConstants#ENOENT} if the file does not exist or if the app tries to delete file
     * in another app's external dir
     * <li>{@link OsConstants#EPERM} a security exception was thrown by {@link #delete}, or if the
     * calling package is a legacy app that doesn't have WRITE_EXTERNAL_STORAGE permission.
     * </ul>
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public int deleteFileForFuse(@NonNull String path, int uid) throws IOException {
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), path);

        try {
            if (isPrivatePackagePathNotAccessibleByCaller(path)) {
                Log.e(TAG, "Can't delete a file in another app's external directory!");
                return OsConstants.ENOENT;
            }

            if (shouldBypassDatabaseAndSetDirtyForFuse(uid, path)) {
                return deleteFileUnchecked(path);
            }

            final boolean shouldBypass = shouldBypassFuseRestrictions(/*forWrite*/ true, path);

            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (!shouldBypass && isCallingPackageRequestingLegacy()) {
                return OsConstants.EPERM;
            }

            final Uri contentUri = FileUtils.getContentUriForPath(path);
            final String where = FileColumns.DATA + " = ?";
            final String[] whereArgs = {path};

            if (delete(contentUri, where, whereArgs) == 0) {
                if (shouldBypass) {
                    return deleteFileUnchecked(path);
                }
                return OsConstants.ENOENT;
            } else {
                // success - 1 file was deleted
                return 0;
            }

        } catch (SecurityException e) {
            Log.e(TAG, "File deletion not allowed", e);
            return OsConstants.EPERM;
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    // These need to stay in sync with MediaProviderWrapper.cpp's DirectoryAccessRequestType enum
    @IntDef(flag = true, prefix = { "DIRECTORY_ACCESS_FOR_" }, value = {
            DIRECTORY_ACCESS_FOR_READ,
            DIRECTORY_ACCESS_FOR_WRITE,
            DIRECTORY_ACCESS_FOR_CREATE,
            DIRECTORY_ACCESS_FOR_DELETE,
    })
    @Retention(RetentionPolicy.SOURCE)
    @VisibleForTesting
    @interface DirectoryAccessType {}

    @VisibleForTesting
    static final int DIRECTORY_ACCESS_FOR_READ = 1;

    @VisibleForTesting
    static final int DIRECTORY_ACCESS_FOR_WRITE = 2;

    @VisibleForTesting
    static final int DIRECTORY_ACCESS_FOR_CREATE = 3;

    @VisibleForTesting
    static final int DIRECTORY_ACCESS_FOR_DELETE = 4;

    /**
     * Checks whether the app with the given UID is allowed to access the directory denoted by the
     * given path.
     *
     * @param path directory's path
     * @param uid UID of the requesting app
     * @param accessType type of access being requested - eg {@link
     * MediaProvider#DIRECTORY_ACCESS_FOR_READ}
     * @return 0 if it's allowed to access the directory, {@link OsConstants#ENOENT} for attempts
     * to access a private package path in Android/data or Android/obb the caller doesn't have
     * access to, and otherwise {@link OsConstants#EACCES} if the calling package is a legacy app
     * that doesn't have READ_EXTERNAL_STORAGE permission or for other invalid attempts to access
     * Android/data or Android/obb dirs.
     *
     * Called from JNI in jni/MediaProviderWrapper.cpp
     */
    @Keep
    public int isDirAccessAllowedForFuse(@NonNull String path, int uid,
            @DirectoryAccessType int accessType) {
        Preconditions.checkArgumentInRange(accessType, 1, DIRECTORY_ACCESS_FOR_DELETE,
                "accessType");

        final boolean forRead = accessType == DIRECTORY_ACCESS_FOR_READ;
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        PulledMetrics.logFileAccessViaFuse(getCallingUidOrSelf(), path);
        try {
            if ("/storage/emulated".equals(path)) {
                return OsConstants.EPERM;
            }
            if (isPrivatePackagePathNotAccessibleByCaller(path)) {
                Log.e(TAG, "Can't access another app's external directory!");
                return OsConstants.ENOENT;
            }

            if (shouldBypassFuseRestrictions(/* forWrite= */ !forRead, path)) {
                return 0;
            }

            // Do not allow apps that reach this point to access Android/data or Android/obb dirs.
            // Creation should be via getContext().getExternalFilesDir() etc methods.
            // Reads and writes on primary volumes should be via mount views of lowerfs for apps
            // that get special access to these directories.
            // Reads and writes on secondary volumes would be provided via an early return from
            // shouldBypassFuseRestrictions above (again just for apps with special access).
            if (isDataOrObbPath(path)) {
                return OsConstants.EACCES;
            }

            // Legacy apps that made is this far don't have the right storage permission and hence
            // are not allowed to access anything other than their external app directory
            if (isCallingPackageRequestingLegacy()) {
                return OsConstants.EACCES;
            }
            // This is a non-legacy app. Rest of the directories are generally writable
            // except for non-default top-level directories.
            if (!forRead) {
                final String[] relativePath = sanitizePath(extractRelativePath(path));
                if (relativePath.length == 0) {
                    Log.e(TAG,
                            "Directory update not allowed on invalid relative path for " + path);
                    return OsConstants.EPERM;
                }
                final boolean isTopLevelDir =
                        relativePath.length == 1 && TextUtils.isEmpty(relativePath[0]);
                if (isTopLevelDir) {
                    // We don't allow deletion of any top-level folders
                    if (accessType == DIRECTORY_ACCESS_FOR_DELETE) {
                        Log.e(TAG, "Deleting top level directories are not allowed!");
                        return OsConstants.EACCES;
                    }

                    // We allow creating or writing to default top-level folders, but we don't
                    // allow creation or writing to non-default top-level folders.
                    if ((accessType == DIRECTORY_ACCESS_FOR_CREATE
                            || accessType == DIRECTORY_ACCESS_FOR_WRITE)
                            && FileUtils.isDefaultDirectoryName(extractDisplayName(path))) {
                        return 0;
                    }

                    Log.e(TAG,
                            "Creating or writing to a non-default top level directory is not "
                                    + "allowed!");
                    return OsConstants.EACCES;
                }
            }

            return 0;
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    @Keep
    public boolean isUidAllowedAccessToDataOrObbPathForFuse(int uid, String path) {
        final LocalCallingIdentity token =
                clearLocalCallingIdentity(getCachedCallingIdentityForFuse(uid));
        try {
            return isCallingIdentityAllowedAccessToDataOrObbPath(
                    extractRelativePathWithDisplayName(path));
        } finally {
            restoreLocalCallingIdentity(token);
        }
    }

    private boolean isCallingIdentityAllowedAccessToDataOrObbPath(String relativePath) {
        // Files under the apps own private directory
        final String appSpecificDir = extractOwnerPackageNameFromRelativePath(relativePath);

        if (appSpecificDir != null && isCallingIdentitySharedPackageName(appSpecificDir)) {
            return true;
        }
        // This is a private-package relativePath; return true if accessible by the caller
        return isCallingIdentityAllowedSpecialPrivatePathAccess(relativePath);
    }

    /**
     * @return true iff the caller has installer privileges which gives write access to obb dirs.
     */
    private boolean isCallingIdentityAllowedInstallerAccess() {
        final boolean hasWrite = mCallingIdentity.get().
                hasPermission(PERMISSION_WRITE_EXTERNAL_STORAGE);

        if (!hasWrite) {
            return false;
        }

        // We're only willing to give out installer access if they also hold
        // runtime permission; this is a firm CDD requirement
        final boolean hasInstall = mCallingIdentity.get().
                hasPermission(PERMISSION_INSTALL_PACKAGES);

        if (hasInstall) {
            return true;
        }
        // OPSTR_REQUEST_INSTALL_PACKAGES is granted/denied per package but vold can't
        // update mountpoints of a specific package. So, check the appop for all packages
        // sharing the uid and allow same level of storage access for all packages even if
        // one of the packages has the appop granted.
        // To maintain consistency of access in primary volume and secondary volumes use the same
        // logic as we do for Zygote.MOUNT_EXTERNAL_INSTALLER view.
        return mCallingIdentity.get().hasPermission(APPOP_REQUEST_INSTALL_PACKAGES_FOR_SHARED_UID);
    }

    private String getExternalStorageProviderAuthority() {
        if (SdkLevel.isAtLeastS()) {
            return getExternalStorageProviderAuthorityFromDocumentsContract();
        }
        return MediaStore.EXTERNAL_STORAGE_PROVIDER_AUTHORITY;
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private String getExternalStorageProviderAuthorityFromDocumentsContract() {
        return DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY;
    }

    private String getDownloadsProviderAuthority() {
        if (SdkLevel.isAtLeastS()) {
            return getDownloadsProviderAuthorityFromDocumentsContract();
        }
        return DOWNLOADS_PROVIDER_AUTHORITY;
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private String getDownloadsProviderAuthorityFromDocumentsContract() {
        return DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY;
    }

    private boolean isCallingIdentityDownloadProvider() {
        return getCallingUidOrSelf() == mDownloadsAuthorityAppId;
    }

    private boolean isCallingIdentityExternalStorageProvider() {
        return getCallingUidOrSelf() == mExternalStorageAuthorityAppId;
    }

    private boolean isCallingIdentityMtp() {
        return mCallingIdentity.get().hasPermission(PERMISSION_ACCESS_MTP);
    }

    /**
     * The following apps have access to all private-app directories on secondary volumes:
     *    * ExternalStorageProvider
     *    * DownloadProvider
     *    * Signature apps with ACCESS_MTP permission granted
     *      (Note: For Android R we also allow privileged apps with ACCESS_MTP to access all
     *      private-app directories, this additional access is removed for Android S+).
     *
     * Installer apps can only access private-app directories on Android/obb.
     *
     * @param relativePath the relative path of the file to access
     */
    private boolean isCallingIdentityAllowedSpecialPrivatePathAccess(String relativePath) {
        if (SdkLevel.isAtLeastS()) {
            return isMountModeAllowedPrivatePathAccess(getCallingUidOrSelf(), getCallingPackage(),
                    relativePath);
        } else {
            if (isCallingIdentityDownloadProvider() ||
                    isCallingIdentityExternalStorageProvider() || isCallingIdentityMtp()) {
                return true;
            }
            return (isObbOrChildRelativePath(relativePath) &&
                    isCallingIdentityAllowedInstallerAccess());
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    private boolean isMountModeAllowedPrivatePathAccess(int uid, String packageName,
            String relativePath) {
        // This is required as only MediaProvider (package with WRITE_MEDIA_STORAGE) can access
        // mount modes.
        final CallingIdentity token = clearCallingIdentity();
        try {
            final int mountMode = mStorageManager.getExternalStorageMountMode(uid, packageName);
            switch (mountMode) {
                case StorageManager.MOUNT_MODE_EXTERNAL_ANDROID_WRITABLE:
                case StorageManager.MOUNT_MODE_EXTERNAL_PASS_THROUGH:
                    return true;
                case StorageManager.MOUNT_MODE_EXTERNAL_INSTALLER:
                    return isObbOrChildRelativePath(relativePath);
            }
        } catch (Exception e) {
            Log.w(TAG, "Caller does not have the permissions to access mount modes: ", e);
        } finally {
            restoreCallingIdentity(token);
        }
        return false;
    }

    private boolean checkCallingPermissionGlobal(Uri uri, boolean forWrite) {
        // System internals can work with all media
        if (isCallingPackageSelf() || isCallingPackageShell()) {
            return true;
        }

        // Apps that have permission to manage external storage can work with all files
        if (isCallingPackageManager()) {
            return true;
        }

        // Check if caller is known to be owner of this item, to speed up
        // performance of our permission checks
        final int table = matchUri(uri, true);
        switch (table) {
            case AUDIO_MEDIA_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
            case FILES_ID:
            case DOWNLOADS_ID:
                final long id = ContentUris.parseId(uri);
                if (mCallingIdentity.get().isOwned(id)) {
                    return true;
                }
                break;
            default:
                // continue below
        }

        // Check whether the uri is a specific table or not. Don't allow the global access to these
        // table uris
        switch (table) {
            case AUDIO_MEDIA:
            case IMAGES_MEDIA:
            case VIDEO_MEDIA:
            case DOWNLOADS:
            case FILES:
            case AUDIO_ALBUMS:
            case AUDIO_ARTISTS:
            case AUDIO_GENRES:
            case AUDIO_PLAYLISTS:
                return false;
            default:
                // continue below
        }

        // Outstanding grant means they get access
        return isUriPermissionGranted(uri, forWrite);
    }

    /**
     * Returns any uri that is granted from the set of Uris passed.
     */
    private @Nullable Uri getPermissionGrantedUri(@NonNull List<Uri> uris, boolean forWrite) {
        for (Uri uri : uris) {
            if (isUriPermissionGranted(uri, forWrite)) {
                return uri;
            }
        }
        return null;
    }

    private boolean isUriPermissionGranted(Uri uri, boolean forWrite) {
        final int modeFlags = forWrite
                ? Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                : Intent.FLAG_GRANT_READ_URI_PERMISSION;
        int uriPermission = getContext().checkUriPermission(uri, mCallingIdentity.get().pid,
                mCallingIdentity.get().uid, modeFlags);
        return uriPermission == PERMISSION_GRANTED;
    }

    @VisibleForTesting
    public boolean isFuseThread() {
        return FuseDaemon.native_is_fuse_thread();
    }

    @VisibleForTesting
    public boolean getBooleanDeviceConfig(String key, boolean defaultValue) {
        if (!canReadDeviceConfig(key, defaultValue)) {
            return defaultValue;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, key,
                    defaultValue);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @VisibleForTesting
    public int getIntDeviceConfig(String key, int defaultValue) {
        if (!canReadDeviceConfig(key, defaultValue)) {
            return defaultValue;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            return DeviceConfig.getInt(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, key,
                    defaultValue);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @VisibleForTesting
    public int getIntDeviceConfig(String namespace, String key, int defaultValue) {
        if (!canReadDeviceConfig(key, defaultValue)) {
            return defaultValue;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            return DeviceConfig.getInt(namespace, key, defaultValue);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    @VisibleForTesting
    public String getStringDeviceConfig(String key, String defaultValue) {
        if (!canReadDeviceConfig(key, defaultValue)) {
            return defaultValue;
        }

        final long token = Binder.clearCallingIdentity();
        try {
            return DeviceConfig.getString(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, key,
                    defaultValue);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private static <T> boolean canReadDeviceConfig(String key, T defaultValue) {
        if (SdkLevel.isAtLeastS()) {
            return true;
        }

        Log.w(TAG, "Cannot read device config before Android S. Returning defaultValue: "
                + defaultValue + " for key: " + key);
        return false;
    }

    @VisibleForTesting
    public void addOnPropertiesChangedListener(OnPropertiesChangedListener listener) {
        if (!SdkLevel.isAtLeastS()) {
            Log.w(TAG, "Cannot add device config changed listener before Android S");
            return;
        }

        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
                BackgroundThread.getExecutor(), listener);
    }

    @Deprecated
    private boolean checkCallingPermissionAudio(boolean forWrite, String callingPackage) {
        if (forWrite) {
            return mCallingIdentity.get().hasPermission(PERMISSION_WRITE_AUDIO);
        } else {
            // write permission should be enough for reading as well
            return mCallingIdentity.get().hasPermission(PERMISSION_READ_AUDIO)
                    || mCallingIdentity.get().hasPermission(PERMISSION_WRITE_AUDIO);
        }
    }

    @Deprecated
    private boolean checkCallingPermissionVideo(boolean forWrite, String callingPackage) {
        if (forWrite) {
            return mCallingIdentity.get().hasPermission(PERMISSION_WRITE_VIDEO);
        } else {
            // write permission should be enough for reading as well
            return mCallingIdentity.get().hasPermission(PERMISSION_READ_VIDEO)
                    || mCallingIdentity.get().hasPermission(PERMISSION_WRITE_VIDEO);
        }
    }

    @Deprecated
    private boolean checkCallingPermissionImages(boolean forWrite, String callingPackage) {
        if (forWrite) {
            return mCallingIdentity.get().hasPermission(PERMISSION_WRITE_IMAGES);
        } else {
            // write permission should be enough for reading as well
            return mCallingIdentity.get().hasPermission(PERMISSION_READ_IMAGES)
                    || mCallingIdentity.get().hasPermission(PERMISSION_WRITE_IMAGES);
        }
    }

    /**
     * Enforce that caller has access to the given {@link Uri}.
     *
     * @throws SecurityException if access isn't allowed.
     */
    private void enforceCallingPermission(@NonNull Uri uri, @NonNull Bundle extras,
            boolean forWrite) {
        Trace.beginSection("enforceCallingPermission");
        try {
            enforceCallingPermissionInternal(uri, extras, forWrite);
        } finally {
            Trace.endSection();
        }
    }

    private void enforceCallingPermission(@NonNull Collection<Uri> uris, boolean forWrite) {
        for (Uri uri : uris) {
            enforceCallingPermission(uri, Bundle.EMPTY, forWrite);
        }
    }

    private void enforceCallingPermissionInternal(@NonNull Uri uri, @NonNull Bundle extras,
            boolean forWrite) {
        Objects.requireNonNull(uri);
        Objects.requireNonNull(extras);

        // Try a simple global check first before falling back to performing a
        // simple query to probe for access.
        if (checkCallingPermissionGlobal(uri, forWrite)) {
            // Access allowed, yay!
            return;
        }

        // For redacted URI proceed with its corresponding URI as query builder doesn't support
        // redacted URIs for fetching a database row
        // NOTE: The grants (if any) must have been on redacted URI hence global check requires
        // redacted URI
        Uri redactedUri = null;
        if (isRedactedUri(uri)) {
            redactedUri = uri;
            uri = getUriForRedactedUri(uri);
        }

        final DatabaseHelper helper;
        try {
            helper = getDatabaseForUri(uri);
        } catch (VolumeNotFoundException e) {
            throw e.rethrowAsIllegalArgumentException();
        }

        final boolean allowHidden = isCallingPackageAllowedHidden();
        final int table = matchUri(uri, allowHidden);

        final String selection = extras.getString(QUERY_ARG_SQL_SELECTION);
        final String[] selectionArgs = extras.getStringArray(QUERY_ARG_SQL_SELECTION_ARGS);

        // First, check to see if caller has direct write access
        if (forWrite) {
            final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_UPDATE, table, uri, extras, null);
            qb.allowColumn(SQLiteQueryBuilder.ROWID_COLUMN);
            try (Cursor c = qb.query(helper, new String[] { SQLiteQueryBuilder.ROWID_COLUMN },
                    selection, selectionArgs, null, null, null, null, null)) {
                if (c.moveToFirst()) {
                    // Direct write access granted, yay!
                    return;
                }
            }
        }

        // We only allow the user to grant access to specific media items in
        // strongly typed collections; never to broad collections
        boolean allowUserGrant = false;
        final int matchUri = matchUri(uri, true);
        switch (matchUri) {
            case IMAGES_MEDIA_ID:
            case AUDIO_MEDIA_ID:
            case VIDEO_MEDIA_ID:
                allowUserGrant = true;
                break;
        }

        // Second, check to see if caller has direct read access
        final SQLiteQueryBuilder qb = getQueryBuilder(TYPE_QUERY, table, uri, extras, null);
        qb.allowColumn(SQLiteQueryBuilder.ROWID_COLUMN);
        try (Cursor c = qb.query(helper, new String[] { SQLiteQueryBuilder.ROWID_COLUMN },
                selection, selectionArgs, null, null, null, null, null)) {
            if (c.moveToFirst()) {
                if (!forWrite) {
                    // Direct read access granted, yay!
                    return;
                } else if (allowUserGrant) {
                    // Caller has read access, but they wanted to write, and
                    // they'll need to get the user to grant that access
                    final Context context = getContext();
                    final Collection<Uri> uris = Arrays.asList(uri);
                    final PendingIntent intent = MediaStore
                            .createWriteRequest(ContentResolver.wrap(this), uris);

                    final Icon icon = getCollectionIcon(uri);
                    final RemoteAction action = new RemoteAction(icon,
                            context.getText(R.string.permission_required_action),
                            context.getText(R.string.permission_required_action),
                            intent);

                    throw new RecoverableSecurityException(new SecurityException(
                            getCallingPackageOrSelf() + " has no access to " + uri),
                            context.getText(R.string.permission_required), action);
                }
            }
        }

        if (redactedUri != null) uri = redactedUri;
        throw new SecurityException(getCallingPackageOrSelf() + " has no access to " + uri);
    }

    private Icon getCollectionIcon(Uri uri) {
        final PackageManager pm = getContext().getPackageManager();
        final String type = uri.getPathSegments().get(1);
        final String groupName;
        switch (type) {
            default: groupName = android.Manifest.permission_group.STORAGE; break;
        }
        try {
            final PermissionGroupInfo perm = pm.getPermissionGroupInfo(groupName, 0);
            return Icon.createWithResource(perm.packageName, perm.icon);
        } catch (NameNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    private void checkAccess(@NonNull Uri uri, @NonNull Bundle extras, @NonNull File file,
            boolean isWrite) throws FileNotFoundException {
        // First, does caller have the needed row-level access?
        enforceCallingPermission(uri, extras, isWrite);

        // Second, does the path look consistent?
        if (!FileUtils.contains(Environment.getStorageDirectory(), file)) {
            checkWorldReadAccess(file.getAbsolutePath());
        }
    }

    /**
     * Check whether the path is a world-readable file
     */
    @VisibleForTesting
    public static void checkWorldReadAccess(String path) throws FileNotFoundException {
        // Path has already been canonicalized, and we relax the check to look
        // at groups to support runtime storage permissions.
        final int accessBits = path.startsWith("/storage/") ? OsConstants.S_IRGRP
                : OsConstants.S_IROTH;
        try {
            StructStat stat = Os.stat(path);
            if (OsConstants.S_ISREG(stat.st_mode) &&
                ((stat.st_mode & accessBits) == accessBits)) {
                checkLeadingPathComponentsWorldExecutable(path);
                return;
            }
        } catch (ErrnoException e) {
            // couldn't stat the file, either it doesn't exist or isn't
            // accessible to us
        }

        throw new FileNotFoundException("Can't access " + path);
    }

    private static void checkLeadingPathComponentsWorldExecutable(String filePath)
            throws FileNotFoundException {
        File parent = new File(filePath).getParentFile();

        // Path has already been canonicalized, and we relax the check to look
        // at groups to support runtime storage permissions.
        final int accessBits = filePath.startsWith("/storage/") ? OsConstants.S_IXGRP
                : OsConstants.S_IXOTH;

        while (parent != null) {
            if (! parent.exists()) {
                // parent dir doesn't exist, give up
                throw new FileNotFoundException("access denied");
            }
            try {
                StructStat stat = Os.stat(parent.getPath());
                if ((stat.st_mode & accessBits) != accessBits) {
                    // the parent dir doesn't have the appropriate access
                    throw new FileNotFoundException("Can't access " + filePath);
                }
            } catch (ErrnoException e1) {
                // couldn't stat() parent
                throw new FileNotFoundException("Can't access " + filePath);
            }
            parent = parent.getParentFile();
        }
    }

    @VisibleForTesting
    static class FallbackException extends Exception {
        private final int mThrowSdkVersion;

        public FallbackException(String message, int throwSdkVersion) {
            super(message);
            mThrowSdkVersion = throwSdkVersion;
        }

        public FallbackException(String message, Throwable cause, int throwSdkVersion) {
            super(message, cause);
            mThrowSdkVersion = throwSdkVersion;
        }

        @Override
        public String getMessage() {
            if (getCause() != null) {
                return super.getMessage() + ": " + getCause().getMessage();
            } else {
                return super.getMessage();
            }
        }

        public IllegalArgumentException rethrowAsIllegalArgumentException() {
            throw new IllegalArgumentException(getMessage());
        }

        public Cursor translateForQuery(int targetSdkVersion) {
            if (targetSdkVersion >= mThrowSdkVersion) {
                throw new IllegalArgumentException(getMessage());
            } else {
                Log.w(TAG, getMessage());
                return null;
            }
        }

        public Uri translateForInsert(int targetSdkVersion) {
            if (targetSdkVersion >= mThrowSdkVersion) {
                throw new IllegalArgumentException(getMessage());
            } else {
                Log.w(TAG, getMessage());
                return null;
            }
        }

        public int translateForBulkInsert(int targetSdkVersion) {
            if (targetSdkVersion >= mThrowSdkVersion) {
                throw new IllegalArgumentException(getMessage());
            } else {
                Log.w(TAG, getMessage());
                return 0;
            }
        }

        public int translateForUpdateDelete(int targetSdkVersion) {
            if (targetSdkVersion >= mThrowSdkVersion) {
                throw new IllegalArgumentException(getMessage());
            } else {
                Log.w(TAG, getMessage());
                return 0;
            }
        }
    }

    @VisibleForTesting
    static class VolumeNotFoundException extends FallbackException {
        public VolumeNotFoundException(String volumeName) {
            super("Volume " + volumeName + " not found", Build.VERSION_CODES.Q);
        }
    }

    @VisibleForTesting
    static class VolumeArgumentException extends FallbackException {
        public VolumeArgumentException(File actual, Collection<File> allowed) {
            super("Requested path " + actual + " doesn't appear under " + allowed,
                    Build.VERSION_CODES.Q);
        }
    }

    public List<String> getSupportedTranscodingRelativePaths() {
        return mTranscodeHelper.getSupportedRelativePaths();
    }

    public List<String> getSupportedUncachedRelativePaths() {
        return StringUtils.verifySupportedUncachedRelativePaths(
                       StringUtils.getStringArrayConfig(getContext(),
                               R.array.config_supported_uncached_relative_paths));
    }

    /**
     * Creating a new method for Transcoding to avoid any merge conflicts.
     * TODO(b/170465810): Remove this when the code is refactored.
     */
    @NonNull DatabaseHelper getDatabaseForUriForTranscoding(Uri uri)
            throws VolumeNotFoundException {
        return getDatabaseForUri(uri);
    }

    private @NonNull DatabaseHelper getDatabaseForUri(Uri uri) throws VolumeNotFoundException {
        final String volumeName = resolveVolumeName(uri);
        synchronized (mAttachedVolumes) {
            boolean volumeAttached = false;
            UserHandle user = mCallingIdentity.get().getUser();
            for (MediaVolume vol : mAttachedVolumes) {
                if (vol.getName().equals(volumeName)
                        && (vol.isVisibleToUser(user) || vol.isPublicVolume()) ) {
                    volumeAttached = true;
                    break;
                }
            }
            if (!volumeAttached) {
                // Dump some more debug info
                Log.e(TAG, "Volume " + volumeName + " not found, calling identity: "
                        + user + ", attached volumes: " + mAttachedVolumes);
                throw new VolumeNotFoundException(volumeName);
            }
        }
        if (MediaStore.VOLUME_INTERNAL.equals(volumeName)) {
            return mInternalDatabase;
        } else {
            return mExternalDatabase;
        }
    }

    static boolean isMediaDatabaseName(String name) {
        if (INTERNAL_DATABASE_NAME.equals(name)) {
            return true;
        }
        if (EXTERNAL_DATABASE_NAME.equals(name)) {
            return true;
        }
        if (name.startsWith("external-") && name.endsWith(".db")) {
            return true;
        }
        return false;
    }

    private @NonNull Uri getBaseContentUri(@NonNull String volumeName) {
        return MediaStore.AUTHORITY_URI.buildUpon().appendPath(volumeName).build();
    }

    public Uri attachVolume(MediaVolume volume, boolean validate) {
        if (mCallingIdentity.get().pid != android.os.Process.myPid()) {
            throw new SecurityException(
                    "Opening and closing databases not allowed.");
        }

        final String volumeName = volume.getName();

        // Quick check for shady volume names
        MediaStore.checkArgumentVolumeName(volumeName);

        // Quick check that volume actually exists
        if (!MediaStore.VOLUME_INTERNAL.equals(volumeName) && validate) {
            try {
                getVolumePath(volumeName);
            } catch (IOException e) {
                throw new IllegalArgumentException(
                        "Volume " + volume + " currently unavailable", e);
            }
        }

        synchronized (mAttachedVolumes) {
            mAttachedVolumes.add(volume);
        }

        final ContentResolver resolver = getContext().getContentResolver();
        final Uri uri = getBaseContentUri(volumeName);
        // TODO(b/182396009) we probably also want to notify clone profile (and vice versa)
        resolver.notifyChange(getBaseContentUri(volumeName), null);

        if (LOGV) Log.v(TAG, "Attached volume: " + volume);
        if (!MediaStore.VOLUME_INTERNAL.equals(volumeName)) {
            // Also notify on synthetic view of all devices
            resolver.notifyChange(getBaseContentUri(MediaStore.VOLUME_EXTERNAL), null);

            ForegroundThread.getExecutor().execute(() -> {
                mExternalDatabase.runWithTransaction((db) -> {
                    ensureDefaultFolders(volume, db);
                    ensureThumbnailsValid(volume, db);
                    return null;
                });

                // We just finished the database operation above, we know that
                // it's ready to answer queries, so notify our DocumentProvider
                // so it can answer queries without risking ANR
                MediaDocumentsProvider.onMediaStoreReady(getContext());
            });
        }
        return uri;
    }

    private void detachVolume(Uri uri) {
        final String volumeName = MediaStore.getVolumeName(uri);
        try {
            detachVolume(getVolume(volumeName));
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find volume for URI " + uri, e) ;
        }
    }

    public boolean isVolumeAttached(MediaVolume volume) {
        synchronized (mAttachedVolumes) {
            return mAttachedVolumes.contains(volume);
        }
    }

    public void detachVolume(MediaVolume volume) {
        if (mCallingIdentity.get().pid != android.os.Process.myPid()) {
            throw new SecurityException(
                    "Opening and closing databases not allowed.");
        }

        final String volumeName = volume.getName();

        // Quick check for shady volume names
        MediaStore.checkArgumentVolumeName(volumeName);

        if (MediaStore.VOLUME_INTERNAL.equals(volumeName)) {
            throw new UnsupportedOperationException(
                    "Deleting the internal volume is not allowed");
        }

        // Signal any scanning to shut down
        mMediaScanner.onDetachVolume(volume);

        synchronized (mAttachedVolumes) {
            mAttachedVolumes.remove(volume);
        }

        final ContentResolver resolver = getContext().getContentResolver();
        final Uri uri = getBaseContentUri(volumeName);
        resolver.notifyChange(getBaseContentUri(volumeName), null);

        if (!MediaStore.VOLUME_INTERNAL.equals(volumeName)) {
            // Also notify on synthetic view of all devices
            resolver.notifyChange(getBaseContentUri(MediaStore.VOLUME_EXTERNAL), null);
        }

        if (LOGV) Log.v(TAG, "Detached volume: " + volumeName);
    }

    @GuardedBy("mAttachedVolumes")
    private final ArraySet<MediaVolume> mAttachedVolumes = new ArraySet<>();
    @GuardedBy("mCustomCollators")
    private final ArraySet<String> mCustomCollators = new ArraySet<>();

    private MediaScanner mMediaScanner;

    private DatabaseHelper mInternalDatabase;
    private DatabaseHelper mExternalDatabase;
    private PickerDbFacade mPickerDbFacade;
    private ExternalDbFacade mExternalDbFacade;
    private PickerDataLayer mPickerDataLayer;
    private PickerSyncController mPickerSyncController;
    private TranscodeHelper mTranscodeHelper;

    // name of the volume currently being scanned by the media scanner (or null)
    private String mMediaScannerVolume;

    // current FAT volume ID
    private int mVolumeId = -1;

    // WARNING: the values of IMAGES_MEDIA, AUDIO_MEDIA, and VIDEO_MEDIA and AUDIO_PLAYLISTS
    // are stored in the "files" table, so do not renumber them unless you also add
    // a corresponding database upgrade step for it.
    static final int IMAGES_MEDIA = 1;
    static final int IMAGES_MEDIA_ID = 2;
    static final int IMAGES_MEDIA_ID_THUMBNAIL = 3;
    static final int IMAGES_THUMBNAILS = 4;
    static final int IMAGES_THUMBNAILS_ID = 5;

    static final int AUDIO_MEDIA = 100;
    static final int AUDIO_MEDIA_ID = 101;
    static final int AUDIO_MEDIA_ID_GENRES = 102;
    static final int AUDIO_MEDIA_ID_GENRES_ID = 103;
    static final int AUDIO_GENRES = 106;
    static final int AUDIO_GENRES_ID = 107;
    static final int AUDIO_GENRES_ID_MEMBERS = 108;
    static final int AUDIO_GENRES_ALL_MEMBERS = 109;
    static final int AUDIO_PLAYLISTS = 110;
    static final int AUDIO_PLAYLISTS_ID = 111;
    static final int AUDIO_PLAYLISTS_ID_MEMBERS = 112;
    static final int AUDIO_PLAYLISTS_ID_MEMBERS_ID = 113;
    static final int AUDIO_ARTISTS = 114;
    static final int AUDIO_ARTISTS_ID = 115;
    static final int AUDIO_ALBUMS = 116;
    static final int AUDIO_ALBUMS_ID = 117;
    static final int AUDIO_ARTISTS_ID_ALBUMS = 118;
    static final int AUDIO_ALBUMART = 119;
    static final int AUDIO_ALBUMART_ID = 120;
    static final int AUDIO_ALBUMART_FILE_ID = 121;

    static final int VIDEO_MEDIA = 200;
    static final int VIDEO_MEDIA_ID = 201;
    static final int VIDEO_MEDIA_ID_THUMBNAIL = 202;
    static final int VIDEO_THUMBNAILS = 203;
    static final int VIDEO_THUMBNAILS_ID = 204;

    static final int VOLUMES = 300;
    static final int VOLUMES_ID = 301;

    static final int MEDIA_SCANNER = 500;

    static final int FS_ID = 600;
    static final int VERSION = 601;

    static final int FILES = 700;
    static final int FILES_ID = 701;

    static final int DOWNLOADS = 800;
    static final int DOWNLOADS_ID = 801;

    static final int PICKER = 900;
    static final int PICKER_ID = 901;
    static final int PICKER_INTERNAL_MEDIA = 902;
    static final int PICKER_INTERNAL_ALBUMS = 903;
    static final int PICKER_UNRELIABLE_VOLUME = 904;

    private static final HashSet<Integer> REDACTED_URI_SUPPORTED_TYPES = new HashSet<>(
            Arrays.asList(AUDIO_MEDIA_ID, IMAGES_MEDIA_ID, VIDEO_MEDIA_ID, FILES_ID, DOWNLOADS_ID));

    private LocalUriMatcher mUriMatcher;

    private static final String[] PATH_PROJECTION = new String[] {
        MediaStore.MediaColumns._ID,
            MediaStore.MediaColumns.DATA,
    };

    private int matchUri(Uri uri, boolean allowHidden) {
        return mUriMatcher.matchUri(uri, allowHidden);
    }

    static class LocalUriMatcher {
        private final UriMatcher mPublic = new UriMatcher(UriMatcher.NO_MATCH);
        private final UriMatcher mHidden = new UriMatcher(UriMatcher.NO_MATCH);

        public int matchUri(Uri uri, boolean allowHidden) {
            final int publicMatch = mPublic.match(uri);
            if (publicMatch != UriMatcher.NO_MATCH) {
                return publicMatch;
            }

            final int hiddenMatch = mHidden.match(uri);
            if (hiddenMatch != UriMatcher.NO_MATCH) {
                // Detect callers asking about hidden behavior by looking closer when
                // the matchers diverge; we only care about apps that are explicitly
                // targeting a specific public API level.
                if (!allowHidden) {
                    throw new IllegalStateException("Unknown URL: " + uri + " is hidden API");
                }
                return hiddenMatch;
            }

            return UriMatcher.NO_MATCH;
        }

        public LocalUriMatcher(String auth) {
            // Warning: Do not move these exact string matches below "*/.." matches.
            // If "*/.." match is added to mPublic children before "picker/#/#", then while matching
            // "picker/0/10", UriMatcher matches "*" node with "picker" and tries to match "0/10"
            // with children of "*".
            // UriMatcher does not look for exact "picker" string match if it finds * node before
            // it. It finds the first best child match and proceeds the match from there without
            // looking at other siblings.
            mPublic.addURI(auth, "picker", PICKER);
            // TODO(b/195009139): Remove after switching picker URI to new format
            // content://media/picker/<user-id>/<media-id>
            mPublic.addURI(auth, "picker/#/#", PICKER_ID);
            // content://media/picker/<user-id>/<authority>/media/<media-id>
            mPublic.addURI(auth, "picker/#/*/media/*", PICKER_ID);
            // content://media/picker/unreliable/<media_id>
            mPublic.addURI(auth, "picker/unreliable/#", PICKER_UNRELIABLE_VOLUME);
            mPublic.addURI(auth, "*/images/media", IMAGES_MEDIA);
            mPublic.addURI(auth, "*/images/media/#", IMAGES_MEDIA_ID);
            mPublic.addURI(auth, "*/images/media/#/thumbnail", IMAGES_MEDIA_ID_THUMBNAIL);
            mPublic.addURI(auth, "*/images/thumbnails", IMAGES_THUMBNAILS);
            mPublic.addURI(auth, "*/images/thumbnails/#", IMAGES_THUMBNAILS_ID);

            mPublic.addURI(auth, "*/audio/media", AUDIO_MEDIA);
            mPublic.addURI(auth, "*/audio/media/#", AUDIO_MEDIA_ID);
            mPublic.addURI(auth, "*/audio/media/#/genres", AUDIO_MEDIA_ID_GENRES);
            mPublic.addURI(auth, "*/audio/media/#/genres/#", AUDIO_MEDIA_ID_GENRES_ID);
            mPublic.addURI(auth, "*/audio/genres", AUDIO_GENRES);
            mPublic.addURI(auth, "*/audio/genres/#", AUDIO_GENRES_ID);
            mPublic.addURI(auth, "*/audio/genres/#/members", AUDIO_GENRES_ID_MEMBERS);
            // TODO: not actually defined in API, but CTS tested
            mPublic.addURI(auth, "*/audio/genres/all/members", AUDIO_GENRES_ALL_MEMBERS);
            mPublic.addURI(auth, "*/audio/playlists", AUDIO_PLAYLISTS);
            mPublic.addURI(auth, "*/audio/playlists/#", AUDIO_PLAYLISTS_ID);
            mPublic.addURI(auth, "*/audio/playlists/#/members", AUDIO_PLAYLISTS_ID_MEMBERS);
            mPublic.addURI(auth, "*/audio/playlists/#/members/#", AUDIO_PLAYLISTS_ID_MEMBERS_ID);
            mPublic.addURI(auth, "*/audio/artists", AUDIO_ARTISTS);
            mPublic.addURI(auth, "*/audio/artists/#", AUDIO_ARTISTS_ID);
            mPublic.addURI(auth, "*/audio/artists/#/albums", AUDIO_ARTISTS_ID_ALBUMS);
            mPublic.addURI(auth, "*/audio/albums", AUDIO_ALBUMS);
            mPublic.addURI(auth, "*/audio/albums/#", AUDIO_ALBUMS_ID);
            // TODO: not actually defined in API, but CTS tested
            mPublic.addURI(auth, "*/audio/albumart", AUDIO_ALBUMART);
            // TODO: not actually defined in API, but CTS tested
            mPublic.addURI(auth, "*/audio/albumart/#", AUDIO_ALBUMART_ID);
            // TODO: not actually defined in API, but CTS tested
            mPublic.addURI(auth, "*/audio/media/#/albumart", AUDIO_ALBUMART_FILE_ID);

            mPublic.addURI(auth, "*/video/media", VIDEO_MEDIA);
            mPublic.addURI(auth, "*/video/media/#", VIDEO_MEDIA_ID);
            mPublic.addURI(auth, "*/video/media/#/thumbnail", VIDEO_MEDIA_ID_THUMBNAIL);
            mPublic.addURI(auth, "*/video/thumbnails", VIDEO_THUMBNAILS);
            mPublic.addURI(auth, "*/video/thumbnails/#", VIDEO_THUMBNAILS_ID);

            mPublic.addURI(auth, "*/media_scanner", MEDIA_SCANNER);

            // NOTE: technically hidden, since Uri is never exposed
            mPublic.addURI(auth, "*/fs_id", FS_ID);
            // NOTE: technically hidden, since Uri is never exposed
            mPublic.addURI(auth, "*/version", VERSION);

            mHidden.addURI(auth, "picker_internal/media", PICKER_INTERNAL_MEDIA);
            mHidden.addURI(auth, "picker_internal/albums", PICKER_INTERNAL_ALBUMS);
            mHidden.addURI(auth, "*", VOLUMES_ID);
            mHidden.addURI(auth, null, VOLUMES);

            mPublic.addURI(auth, "*/file", FILES);
            mPublic.addURI(auth, "*/file/#", FILES_ID);

            mPublic.addURI(auth, "*/downloads", DOWNLOADS);
            mPublic.addURI(auth, "*/downloads/#", DOWNLOADS_ID);
        }
    }

    /**
     * Set of columns that can be safely mutated by external callers; all other
     * columns are treated as read-only, since they reflect what the media
     * scanner found on disk, and any mutations would be overwritten the next
     * time the media was scanned.
     */
    private static final ArraySet<String> sMutableColumns = new ArraySet<>();

    static {
        sMutableColumns.add(MediaStore.MediaColumns.DATA);
        sMutableColumns.add(MediaStore.MediaColumns.RELATIVE_PATH);
        sMutableColumns.add(MediaStore.MediaColumns.DISPLAY_NAME);
        sMutableColumns.add(MediaStore.MediaColumns.IS_PENDING);
        sMutableColumns.add(MediaStore.MediaColumns.IS_TRASHED);
        sMutableColumns.add(MediaStore.MediaColumns.IS_FAVORITE);
        sMutableColumns.add(MediaStore.MediaColumns.OWNER_PACKAGE_NAME);

        sMutableColumns.add(MediaStore.Audio.AudioColumns.BOOKMARK);

        sMutableColumns.add(MediaStore.Video.VideoColumns.TAGS);
        sMutableColumns.add(MediaStore.Video.VideoColumns.CATEGORY);
        sMutableColumns.add(MediaStore.Video.VideoColumns.BOOKMARK);

        sMutableColumns.add(MediaStore.Audio.Playlists.NAME);
        sMutableColumns.add(MediaStore.Audio.Playlists.Members.AUDIO_ID);
        sMutableColumns.add(MediaStore.Audio.Playlists.Members.PLAY_ORDER);

        sMutableColumns.add(MediaStore.DownloadColumns.DOWNLOAD_URI);
        sMutableColumns.add(MediaStore.DownloadColumns.REFERER_URI);

        sMutableColumns.add(MediaStore.Files.FileColumns.MIME_TYPE);
        sMutableColumns.add(MediaStore.Files.FileColumns.MEDIA_TYPE);
    }

    /**
     * Set of columns that affect placement of files on disk.
     */
    private static final ArraySet<String> sPlacementColumns = new ArraySet<>();

    static {
        sPlacementColumns.add(MediaStore.MediaColumns.DATA);
        sPlacementColumns.add(MediaStore.MediaColumns.RELATIVE_PATH);
        sPlacementColumns.add(MediaStore.MediaColumns.DISPLAY_NAME);
        sPlacementColumns.add(MediaStore.MediaColumns.MIME_TYPE);
        sPlacementColumns.add(MediaStore.MediaColumns.IS_PENDING);
        sPlacementColumns.add(MediaStore.MediaColumns.IS_TRASHED);
        sPlacementColumns.add(MediaStore.MediaColumns.DATE_EXPIRES);
    }

    /**
     * List of abusive custom columns that we're willing to allow via
     * {@link SQLiteQueryBuilder#setProjectionGreylist(List)}.
     */
    static final ArrayList<Pattern> sGreylist = new ArrayList<>();

    private static void addGreylistPattern(String pattern) {
        sGreylist.add(Pattern.compile(" *" + pattern + " *"));
    }

    static {
        final String maybeAs = "( (as )?[_a-z0-9]+)?";
        addGreylistPattern("(?i)[_a-z0-9]+" + maybeAs);
        addGreylistPattern("audio\\._id AS _id");
        addGreylistPattern("(?i)(min|max|sum|avg|total|count|cast)\\(([_a-z0-9]+" + maybeAs + "|\\*)\\)" + maybeAs);
        addGreylistPattern("case when case when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added \\* \\d+ when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added / \\d+ else \\d+ end > case when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified \\* \\d+ when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified / \\d+ else \\d+ end then case when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added \\* \\d+ when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added / \\d+ else \\d+ end else case when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified \\* \\d+ when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified / \\d+ else \\d+ end end as corrected_added_modified");
        addGreylistPattern("MAX\\(case when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken \\* \\d+ when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken / \\d+ else \\d+ end\\)");
        addGreylistPattern("MAX\\(case when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added \\* \\d+ when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added when \\(date_added >= \\d+ and date_added < \\d+\\) then date_added / \\d+ else \\d+ end\\)");
        addGreylistPattern("MAX\\(case when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified \\* \\d+ when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified when \\(date_modified >= \\d+ and date_modified < \\d+\\) then date_modified / \\d+ else \\d+ end\\)");
        addGreylistPattern("\"content://media/[a-z]+/audio/media\"");
        addGreylistPattern("substr\\(_data, length\\(_data\\)-length\\(_display_name\\), 1\\) as filename_prevchar");
        addGreylistPattern("\\*" + maybeAs);
        addGreylistPattern("case when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken \\* \\d+ when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken when \\(datetaken >= \\d+ and datetaken < \\d+\\) then datetaken / \\d+ else \\d+ end");
    }

    public ArrayMap<String, String> getProjectionMap(Class<?>... clazzes) {
        return mExternalDatabase.getProjectionMap(clazzes);
    }

    static <T> boolean containsAny(Set<T> a, Set<T> b) {
        for (T i : b) {
            if (a.contains(i)) {
                return true;
            }
        }
        return false;
    }

    @VisibleForTesting
    static @Nullable Uri computeCommonPrefix(@NonNull List<Uri> uris) {
        if (uris.isEmpty()) return null;

        final Uri base = uris.get(0);
        final List<String> basePath = new ArrayList<>(base.getPathSegments());
        for (int i = 1; i < uris.size(); i++) {
            final List<String> probePath = uris.get(i).getPathSegments();
            for (int j = 0; j < basePath.size() && j < probePath.size(); j++) {
                if (!Objects.equals(basePath.get(j), probePath.get(j))) {
                    // Trim away all remaining common elements
                    while (basePath.size() > j) {
                        basePath.remove(j);
                    }
                }
            }

            final int probeSize = probePath.size();
            while (basePath.size() > probeSize) {
                basePath.remove(probeSize);
            }
        }

        final Uri.Builder builder = base.buildUpon().path(null);
        for (int i = 0; i < basePath.size(); i++) {
            builder.appendPath(basePath.get(i));
        }
        return builder.build();
    }

    public ExternalDbFacade getExternalDbFacade() {
        return mExternalDbFacade;
    }

    public PickerSyncController getPickerSyncController() {
        return mPickerSyncController;
    }

    private boolean isCallingPackageSystemGallery() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_SYSTEM_GALLERY);
    }

    private int getCallingUidOrSelf() {
        return mCallingIdentity.get().uid;
    }

    @Deprecated
    private String getCallingPackageOrSelf() {
        return mCallingIdentity.get().getPackageName();
    }

    @Deprecated
    @VisibleForTesting
    public int getCallingPackageTargetSdkVersion() {
        return mCallingIdentity.get().getTargetSdkVersion();
    }

    @Deprecated
    private boolean isCallingPackageAllowedHidden() {
        return isCallingPackageSelf();
    }

    @Deprecated
    private boolean isCallingPackageSelf() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_SELF);
    }

    @Deprecated
    private boolean isCallingPackageShell() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_SHELL);
    }

    @Deprecated
    private boolean isCallingPackageManager() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_MANAGER);
    }

    @Deprecated
    private boolean isCallingPackageDelegator() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_DELEGATOR);
    }

    @Deprecated
    private boolean isCallingPackageLegacyRead() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_LEGACY_READ);
    }

    @Deprecated
    private boolean isCallingPackageLegacyWrite() {
        return mCallingIdentity.get().hasPermission(PERMISSION_IS_LEGACY_WRITE);
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        writer.println("mThumbSize=" + mThumbSize);
        synchronized (mAttachedVolumes) {
            writer.println("mAttachedVolumes=" + mAttachedVolumes);
        }
        writer.println();

        mVolumeCache.dump(writer);
        writer.println();

        mUserCache.dump(writer);
        writer.println();

        mTranscodeHelper.dump(writer);
        writer.println();

        Logging.dumpPersistent(writer);
    }
}
