/*
 * Copyright (C) 2013 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.externalstorage;

import android.annotation.Nullable;
import android.app.usage.StorageStatsManager;
import android.content.ContentResolver;
import android.content.UriPermission;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.database.MatrixCursor.RowBuilder;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsContract.Root;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DebugUtils;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.FileSystemProvider;
import com.android.internal.util.IndentingPrintWriter;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

public class ExternalStorageProvider extends FileSystemProvider {
    private static final String TAG = "ExternalStorage";

    private static final boolean DEBUG = false;

    public static final String AUTHORITY = "com.android.externalstorage.documents";

    private static final Uri BASE_URI =
            new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY).build();

    // docId format: root:path/to/file

    private static final String[] DEFAULT_ROOT_PROJECTION = new String[] {
            Root.COLUMN_ROOT_ID, Root.COLUMN_FLAGS, Root.COLUMN_ICON, Root.COLUMN_TITLE,
            Root.COLUMN_DOCUMENT_ID, Root.COLUMN_AVAILABLE_BYTES,
    };

    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
            Document.COLUMN_DOCUMENT_ID, Document.COLUMN_MIME_TYPE, Document.COLUMN_DISPLAY_NAME,
            Document.COLUMN_LAST_MODIFIED, Document.COLUMN_FLAGS, Document.COLUMN_SIZE,
    };

    private static class RootInfo {
        public String rootId;
        public String volumeId;
        public UUID storageUuid;
        public int flags;
        public String title;
        public String docId;
        public File visiblePath;
        public File path;
        public boolean reportAvailableBytes = true;
    }

    private static final String ROOT_ID_PRIMARY_EMULATED = "primary";
    private static final String ROOT_ID_HOME = "home";

    private StorageManager mStorageManager;
    private UserManager mUserManager;

    private final Object mRootsLock = new Object();

    @GuardedBy("mRootsLock")
    private ArrayMap<String, RootInfo> mRoots = new ArrayMap<>();

    @Override
    public boolean onCreate() {
        super.onCreate(DEFAULT_DOCUMENT_PROJECTION);

        mStorageManager = getContext().getSystemService(StorageManager.class);
        mUserManager = getContext().getSystemService(UserManager.class);

        updateVolumes();
        return true;
    }

    private void enforceShellRestrictions() {
        if (UserHandle.getCallingAppId() == android.os.Process.SHELL_UID
                && mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
            throw new SecurityException(
                    "Shell user cannot access files for user " + UserHandle.myUserId());
        }
    }

    @Override
    protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
            throws SecurityException {
        enforceShellRestrictions();
        return super.enforceReadPermissionInner(uri, callingPkg, callerToken);
    }

    @Override
    protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
            throws SecurityException {
        enforceShellRestrictions();
        return super.enforceWritePermissionInner(uri, callingPkg, callerToken);
    }

    public void updateVolumes() {
        synchronized (mRootsLock) {
            updateVolumesLocked();
        }
    }

    private void updateVolumesLocked() {
        mRoots.clear();

        VolumeInfo primaryVolume = null;
        final int userId = UserHandle.myUserId();
        final List<VolumeInfo> volumes = mStorageManager.getVolumes();
        for (VolumeInfo volume : volumes) {
            if (!volume.isMountedReadable()) continue;

            final String rootId;
            final String title;
            final UUID storageUuid;
            if (volume.getType() == VolumeInfo.TYPE_EMULATED) {
                // We currently only support a single emulated volume mounted at
                // a time, and it's always considered the primary
                if (DEBUG) Log.d(TAG, "Found primary volume: " + volume);
                rootId = ROOT_ID_PRIMARY_EMULATED;

                if (VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
                    // This is basically the user's primary device storage.
                    // Use device name for the volume since this is likely same thing
                    // the user sees when they mount their phone on another device.
                    String deviceName = Settings.Global.getString(
                            getContext().getContentResolver(), Settings.Global.DEVICE_NAME);

                    // Device name should always be set. In case it isn't, though,
                    // fall back to a localized "Internal Storage" string.
                    title = !TextUtils.isEmpty(deviceName)
                            ? deviceName
                            : getContext().getString(R.string.root_internal_storage);
                    storageUuid = StorageManager.UUID_DEFAULT;
                } else {
                    // This should cover all other storage devices, like an SD card
                    // or USB OTG drive plugged in. Using getBestVolumeDescription()
                    // will give us a nice string like "Samsung SD card" or "SanDisk USB drive"
                    final VolumeInfo privateVol = mStorageManager.findPrivateForEmulated(volume);
                    title = mStorageManager.getBestVolumeDescription(privateVol);
                    storageUuid = StorageManager.convert(privateVol.fsUuid);
                }
            } else if (volume.getType() == VolumeInfo.TYPE_PUBLIC
                    && volume.getMountUserId() == userId) {
                rootId = volume.getFsUuid();
                title = mStorageManager.getBestVolumeDescription(volume);
                storageUuid = null;
            } else {
                // Unsupported volume; ignore
                continue;
            }

            if (TextUtils.isEmpty(rootId)) {
                Log.d(TAG, "Missing UUID for " + volume.getId() + "; skipping");
                continue;
            }
            if (mRoots.containsKey(rootId)) {
                Log.w(TAG, "Duplicate UUID " + rootId + " for " + volume.getId() + "; skipping");
                continue;
            }

            final RootInfo root = new RootInfo();
            mRoots.put(rootId, root);

            root.rootId = rootId;
            root.volumeId = volume.id;
            root.storageUuid = storageUuid;
            root.flags = Root.FLAG_LOCAL_ONLY
                    | Root.FLAG_SUPPORTS_SEARCH
                    | Root.FLAG_SUPPORTS_IS_CHILD;

            final DiskInfo disk = volume.getDisk();
            if (DEBUG) Log.d(TAG, "Disk for root " + rootId + " is " + disk);
            if (disk != null && disk.isSd()) {
                root.flags |= Root.FLAG_REMOVABLE_SD;
            } else if (disk != null && disk.isUsb()) {
                root.flags |= Root.FLAG_REMOVABLE_USB;
            }

            if (!VolumeInfo.ID_EMULATED_INTERNAL.equals(volume.getId())) {
                root.flags |= Root.FLAG_SUPPORTS_EJECT;
            }

            if (volume.isPrimary()) {
                // save off the primary volume for subsequent "Home" dir initialization.
                primaryVolume = volume;
                root.flags |= Root.FLAG_ADVANCED;
            }
            // Dunno when this would NOT be the case, but never hurts to be correct.
            if (volume.isMountedWritable()) {
                root.flags |= Root.FLAG_SUPPORTS_CREATE;
            }
            root.title = title;
            if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
                root.flags |= Root.FLAG_HAS_SETTINGS;
            }
            if (volume.isVisibleForRead(userId)) {
                root.visiblePath = volume.getPathForUser(userId);
            } else {
                root.visiblePath = null;
            }
            root.path = volume.getInternalPathForUser(userId);
            try {
                root.docId = getDocIdForFile(root.path);
            } catch (FileNotFoundException e) {
                throw new IllegalStateException(e);
            }
        }

        // Finally, if primary storage is available we add the "Documents" directory.
        // If I recall correctly the actual directory is created on demand
        // by calling either getPathForUser, or getInternalPathForUser.
        if (primaryVolume != null && primaryVolume.isVisible()) {
            final RootInfo root = new RootInfo();
            root.rootId = ROOT_ID_HOME;
            mRoots.put(root.rootId, root);
            root.title = getContext().getString(R.string.root_documents);

            // Only report bytes on *volumes*...as a matter of policy.
            root.reportAvailableBytes = false;
            root.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_SEARCH
                    | Root.FLAG_SUPPORTS_IS_CHILD;

            // Dunno when this would NOT be the case, but never hurts to be correct.
            if (primaryVolume.isMountedWritable()) {
                root.flags |= Root.FLAG_SUPPORTS_CREATE;
            }

            // Create the "Documents" directory on disk (don't use the localized title).
            root.visiblePath = new File(
                    primaryVolume.getPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
            root.path = new File(
                    primaryVolume.getInternalPathForUser(userId), Environment.DIRECTORY_DOCUMENTS);
            try {
                root.docId = getDocIdForFile(root.path);
            } catch (FileNotFoundException e) {
                throw new IllegalStateException(e);
            }
        }

        Log.d(TAG, "After updating volumes, found " + mRoots.size() + " active roots");

        // Note this affects content://com.android.externalstorage.documents/root/39BD-07C5
        // as well as content://com.android.externalstorage.documents/document/*/children,
        // so just notify on content://com.android.externalstorage.documents/.
        getContext().getContentResolver().notifyChange(BASE_URI, null, false);
    }

    private static String[] resolveRootProjection(String[] projection) {
        return projection != null ? projection : DEFAULT_ROOT_PROJECTION;
    }

    @Override
    protected String getDocIdForFile(File file) throws FileNotFoundException {
        return getDocIdForFileMaybeCreate(file, false);
    }

    private String getDocIdForFileMaybeCreate(File file, boolean createNewDir)
            throws FileNotFoundException {
        String path = file.getAbsolutePath();

        // Find the most-specific root path
        boolean visiblePath = false;
        RootInfo mostSpecificRoot = getMostSpecificRootForPath(path, false);

        if (mostSpecificRoot == null) {
            // Try visible path if no internal path matches. MediaStore uses visible paths.
            visiblePath = true;
            mostSpecificRoot = getMostSpecificRootForPath(path, true);
        }

        if (mostSpecificRoot == null) {
            throw new FileNotFoundException("Failed to find root that contains " + path);
        }

        // Start at first char of path under root
        final String rootPath = visiblePath
                ? mostSpecificRoot.visiblePath.getAbsolutePath()
                : mostSpecificRoot.path.getAbsolutePath();
        if (rootPath.equals(path)) {
            path = "";
        } else if (rootPath.endsWith("/")) {
            path = path.substring(rootPath.length());
        } else {
            path = path.substring(rootPath.length() + 1);
        }

        if (!file.exists() && createNewDir) {
            Log.i(TAG, "Creating new directory " + file);
            if (!file.mkdir()) {
                Log.e(TAG, "Could not create directory " + file);
            }
        }

        return mostSpecificRoot.rootId + ':' + path;
    }

    private RootInfo getMostSpecificRootForPath(String path, boolean visible) {
        // Find the most-specific root path
        RootInfo mostSpecificRoot = null;
        String mostSpecificPath = null;
        synchronized (mRootsLock) {
            for (int i = 0; i < mRoots.size(); i++) {
                final RootInfo root = mRoots.valueAt(i);
                final File rootFile = visible ? root.visiblePath : root.path;
                if (rootFile != null) {
                    final String rootPath = rootFile.getAbsolutePath();
                    if (path.startsWith(rootPath) && (mostSpecificPath == null
                            || rootPath.length() > mostSpecificPath.length())) {
                        mostSpecificRoot = root;
                        mostSpecificPath = rootPath;
                    }
                }
            }
        }

        return mostSpecificRoot;
    }

    @Override
    protected File getFileForDocId(String docId, boolean visible) throws FileNotFoundException {
        return getFileForDocId(docId, visible, true);
    }

    private File getFileForDocId(String docId, boolean visible, boolean mustExist)
            throws FileNotFoundException {
        RootInfo root = getRootFromDocId(docId);
        return buildFile(root, docId, visible, mustExist);
    }

    private Pair<RootInfo, File> resolveDocId(String docId, boolean visible)
            throws FileNotFoundException {
        RootInfo root = getRootFromDocId(docId);
        return Pair.create(root, buildFile(root, docId, visible, true));
    }

    private RootInfo getRootFromDocId(String docId) throws FileNotFoundException {
        final int splitIndex = docId.indexOf(':', 1);
        final String tag = docId.substring(0, splitIndex);

        RootInfo root;
        synchronized (mRootsLock) {
            root = mRoots.get(tag);
        }
        if (root == null) {
            throw new FileNotFoundException("No root for " + tag);
        }

        return root;
    }

    private File buildFile(RootInfo root, String docId, boolean visible, boolean mustExist)
            throws FileNotFoundException {
        final int splitIndex = docId.indexOf(':', 1);
        final String path = docId.substring(splitIndex + 1);

        File target = visible ? root.visiblePath : root.path;
        if (target == null) {
            return null;
        }
        if (!target.exists()) {
            target.mkdirs();
        }
        target = new File(target, path);
        if (mustExist && !target.exists()) {
            throw new FileNotFoundException("Missing file for " + docId + " at " + target);
        }
        return target;
    }

    @Override
    protected Uri buildNotificationUri(String docId) {
        return DocumentsContract.buildChildDocumentsUri(AUTHORITY, docId);
    }

    @Override
    protected void onDocIdChanged(String docId) {
        try {
            // Touch the visible path to ensure that any sdcardfs caches have
            // been updated to reflect underlying changes on disk.
            final File visiblePath = getFileForDocId(docId, true, false);
            if (visiblePath != null) {
                Os.access(visiblePath.getAbsolutePath(), OsConstants.F_OK);
            }
        } catch (FileNotFoundException | ErrnoException ignored) {
        }
    }

    @Override
    public Cursor queryRoots(String[] projection) throws FileNotFoundException {
        final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
        synchronized (mRootsLock) {
            for (RootInfo root : mRoots.values()) {
                final RowBuilder row = result.newRow();
                row.add(Root.COLUMN_ROOT_ID, root.rootId);
                row.add(Root.COLUMN_FLAGS, root.flags);
                row.add(Root.COLUMN_TITLE, root.title);
                row.add(Root.COLUMN_DOCUMENT_ID, root.docId);

                long availableBytes = -1;
                if (root.reportAvailableBytes) {
                    if (root.storageUuid != null) {
                        try {
                            availableBytes = getContext()
                                    .getSystemService(StorageStatsManager.class)
                                    .getFreeBytes(root.storageUuid);
                        } catch (IOException e) {
                            Log.w(TAG, e);
                        }
                    } else {
                        availableBytes = root.path.getUsableSpace();
                    }
                }
                row.add(Root.COLUMN_AVAILABLE_BYTES, availableBytes);
            }
        }
        return result;
    }

    @Override
    public Path findDocumentPath(@Nullable String parentDocId, String childDocId)
            throws FileNotFoundException {
        final Pair<RootInfo, File> resolvedDocId = resolveDocId(childDocId, false);
        final RootInfo root = resolvedDocId.first;
        File child = resolvedDocId.second;

        final File parent = TextUtils.isEmpty(parentDocId)
                        ? root.path
                        : getFileForDocId(parentDocId);

        return new Path(parentDocId == null ? root.rootId : null, findDocumentPath(parent, child));
    }

    private Uri getDocumentUri(String path, List<UriPermission> accessUriPermissions)
            throws FileNotFoundException {
        File doc = new File(path);

        final String docId = getDocIdForFile(doc);

        UriPermission docUriPermission = null;
        UriPermission treeUriPermission = null;
        for (UriPermission uriPermission : accessUriPermissions) {
            final Uri uri = uriPermission.getUri();
            if (AUTHORITY.equals(uri.getAuthority())) {
                boolean matchesRequestedDoc = false;
                if (DocumentsContract.isTreeUri(uri)) {
                    final String parentDocId = DocumentsContract.getTreeDocumentId(uri);
                    if (isChildDocument(parentDocId, docId)) {
                        treeUriPermission = uriPermission;
                        matchesRequestedDoc = true;
                    }
                } else {
                    final String candidateDocId = DocumentsContract.getDocumentId(uri);
                    if (Objects.equals(docId, candidateDocId)) {
                        docUriPermission = uriPermission;
                        matchesRequestedDoc = true;
                    }
                }

                if (matchesRequestedDoc && allowsBothReadAndWrite(uriPermission)) {
                    // This URI permission provides everything an app can get, no need to
                    // further check any other granted URI.
                    break;
                }
            }
        }

        // Full permission URI first.
        if (allowsBothReadAndWrite(treeUriPermission)) {
            return DocumentsContract.buildDocumentUriUsingTree(treeUriPermission.getUri(), docId);
        }

        if (allowsBothReadAndWrite(docUriPermission)) {
            return docUriPermission.getUri();
        }

        // Then partial permission URI.
        if (treeUriPermission != null) {
            return DocumentsContract.buildDocumentUriUsingTree(treeUriPermission.getUri(), docId);
        }

        if (docUriPermission != null) {
            return docUriPermission.getUri();
        }

        throw new SecurityException("The app is not given any access to the document under path " +
                path + " with permissions granted in " + accessUriPermissions);
    }

    private static boolean allowsBothReadAndWrite(UriPermission permission) {
        return permission != null
                && permission.isReadPermission()
                && permission.isWritePermission();
    }

    @Override
    public Cursor querySearchDocuments(String rootId, String query, String[] projection)
            throws FileNotFoundException {
        final File parent;
        synchronized (mRootsLock) {
            parent = mRoots.get(rootId).path;
        }

        return querySearchDocuments(parent, query, projection, Collections.emptySet());
    }

    @Override
    public void ejectRoot(String rootId) {
        final long token = Binder.clearCallingIdentity();
        RootInfo root = mRoots.get(rootId);
        if (root != null) {
            try {
                mStorageManager.unmount(root.volumeId);
            } catch (RuntimeException e) {
                throw new IllegalStateException(e);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ", 160);
        synchronized (mRootsLock) {
            for (int i = 0; i < mRoots.size(); i++) {
                final RootInfo root = mRoots.valueAt(i);
                pw.println("Root{" + root.rootId + "}:");
                pw.increaseIndent();
                pw.printPair("flags", DebugUtils.flagsToString(Root.class, "FLAG_", root.flags));
                pw.println();
                pw.printPair("title", root.title);
                pw.printPair("docId", root.docId);
                pw.println();
                pw.printPair("path", root.path);
                pw.printPair("visiblePath", root.visiblePath);
                pw.decreaseIndent();
                pw.println();
            }
        }
    }

    @Override
    public Bundle call(String method, String arg, Bundle extras) {
        Bundle bundle = super.call(method, arg, extras);
        if (bundle == null && !TextUtils.isEmpty(method)) {
            switch (method) {
                case "getDocIdForFileCreateNewDir": {
                    getContext().enforceCallingPermission(
                            android.Manifest.permission.MANAGE_DOCUMENTS, null);
                    if (TextUtils.isEmpty(arg)) {
                        return null;
                    }
                    try {
                        final String docId = getDocIdForFileMaybeCreate(new File(arg), true);
                        bundle = new Bundle();
                        bundle.putString("DOC_ID", docId);
                    } catch (FileNotFoundException e) {
                        Log.w(TAG, "file '" + arg + "' not found");
                        return null;
                    }
                    break;
                }
                case "getDocumentId": {
                    final String path = arg;
                    final List<UriPermission> accessUriPermissions =
                            extras.getParcelableArrayList(AUTHORITY + ".extra.uriPermissions");

                    try {
                        final Bundle out = new Bundle();
                        final Uri uri = getDocumentUri(path, accessUriPermissions);
                        out.putParcelable(DocumentsContract.EXTRA_URI, uri);
                        return out;
                    } catch (FileNotFoundException e) {
                        throw new IllegalStateException("File in " + path + " is not found.", e);
                    }

                }
                default:
                    Log.w(TAG, "unknown method passed to call(): " + method);
            }
        }
        return bundle;
    }
}
