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

package android.mtp;

import android.media.MediaFile;
import android.os.FileObserver;
import android.os.storage.StorageVolume;
import android.util.Log;

import com.android.internal.util.Preconditions;

import java.io.IOException;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * MtpStorageManager provides functionality for listing, tracking, and notifying MtpServer of
 * filesystem changes. As directories are listed, this class will cache the results,
 * and send events when objects are added/removed from cached directories.
 * {@hide}
 */
public class MtpStorageManager {
    private static final String TAG = MtpStorageManager.class.getSimpleName();
    public static boolean sDebug = false;

    // Inotify flags not provided by FileObserver
    private static final int IN_ONLYDIR = 0x01000000;
    private static final int IN_Q_OVERFLOW = 0x00004000;
    private static final int IN_IGNORED    = 0x00008000;
    private static final int IN_ISDIR = 0x40000000;

    private class MtpObjectObserver extends FileObserver {
        MtpObject mObject;

        MtpObjectObserver(MtpObject object) {
            super(object.getPath().toString(),
                    MOVED_FROM | MOVED_TO | DELETE | CREATE | IN_ONLYDIR
                  | CLOSE_WRITE);
            mObject = object;
        }

        @Override
        public void onEvent(int event, String path) {
            synchronized (MtpStorageManager.this) {
                if ((event & IN_Q_OVERFLOW) != 0) {
                    // We are out of space in the inotify queue.
                    Log.e(TAG, "Received Inotify overflow event!");
                }
                MtpObject obj = mObject.getChild(path);
                if ((event & MOVED_TO) != 0 || (event & CREATE) != 0) {
                    if (sDebug)
                        Log.i(TAG, "Got inotify added event for " + path + " " + event);
                    handleAddedObject(mObject, path, (event & IN_ISDIR) != 0);
                } else if ((event & MOVED_FROM) != 0 || (event & DELETE) != 0) {
                    if (obj == null) {
                        Log.w(TAG, "Object was null in event " + path);
                        return;
                    }
                    if (sDebug)
                        Log.i(TAG, "Got inotify removed event for " + path + " " + event);
                    handleRemovedObject(obj);
                } else if ((event & IN_IGNORED) != 0) {
                    if (sDebug)
                        Log.i(TAG, "inotify for " + mObject.getPath() + " deleted");
                    if (mObject.mObserver != null)
                        mObject.mObserver.stopWatching();
                    mObject.mObserver = null;
                } else if ((event & CLOSE_WRITE) != 0) {
                    if (sDebug)
                        Log.i(TAG, "inotify for " + mObject.getPath() + " CLOSE_WRITE: " + path);
                    handleChangedObject(mObject, path);
                } else {
                    Log.w(TAG, "Got unrecognized event " + path + " " + event);
                }
            }
        }

        @Override
        public void finalize() {
            // If the server shuts down and starts up again, the new server's observers can be
            // invalidated by the finalize() calls of the previous server's observers.
            // Hence, disable the automatic stopWatching() call in FileObserver#finalize, and
            // always call stopWatching() manually whenever an observer should be shut down.
        }
    }

    /**
     * Describes how the object is being acted on, to determine how events are handled.
     */
    private enum MtpObjectState {
        NORMAL,
        FROZEN,             // Object is going to be modified in this session.
        FROZEN_ADDED,       // Object was frozen, and has been added.
        FROZEN_REMOVED,     // Object was frozen, and has been removed.
        FROZEN_ONESHOT_ADD, // Object is waiting for single add event before being unfrozen.
        FROZEN_ONESHOT_DEL, // Object is waiting for single remove event and will then be removed.
    }

    /**
     * Describes the current operation being done on an object. Determines whether observers are
     * created on new folders.
     */
    private enum MtpOperation {
        NONE,     // Any new folders not added as part of the session are immediately observed.
        ADD,      // New folders added as part of the session are immediately observed.
        RENAME,   // Renamed or moved folders are not immediately observed.
        COPY,     // Copied folders are immediately observed iff the original was.
        DELETE,   // Exists for debugging purposes only.
    }

    /** MtpObject represents either a file or directory in an associated storage. **/
    public static class MtpObject {
        private MtpStorage mStorage;
        // null for root objects
        private MtpObject mParent;

        private String mName;
        private int mId;
        private MtpObjectState mState;
        private MtpOperation mOp;

        private boolean mVisited;
        private boolean mIsDir;

        // null if not a directory
        private HashMap<String, MtpObject> mChildren;
        // null if not both a directory and visited
        private FileObserver mObserver;

        MtpObject(String name, int id, MtpStorage storage, MtpObject parent, boolean isDir) {
            mId = id;
            mName = name;
            mStorage = Preconditions.checkNotNull(storage);
            mParent = parent;
            mObserver = null;
            mVisited = false;
            mState = MtpObjectState.NORMAL;
            mIsDir = isDir;
            mOp = MtpOperation.NONE;

            mChildren = mIsDir ? new HashMap<>() : null;
        }

        /** Public methods for getting object info **/

        public String getName() {
            return mName;
        }

        public int getId() {
            return mId;
        }

        public boolean isDir() {
            return mIsDir;
        }

        public int getFormat() {
            return mIsDir ? MtpConstants.FORMAT_ASSOCIATION : MediaFile.getFormatCode(mName, null);
        }

        public int getStorageId() {
            return getRoot().getId();
        }

        public long getModifiedTime() {
            return getPath().toFile().lastModified() / 1000;
        }

        public MtpObject getParent() {
            return mParent;
        }

        public MtpObject getRoot() {
            return isRoot() ? this : mParent.getRoot();
        }

        public long getSize() {
            return mIsDir ? 0 : getPath().toFile().length();
        }

        public Path getPath() {
            return isRoot() ? Paths.get(mName) : mParent.getPath().resolve(mName);
        }

        public boolean isRoot() {
            return mParent == null;
        }

        public String getVolumeName() {
            return mStorage.getVolumeName();
        }

        /** For MtpStorageManager only **/

        private void setName(String name) {
            mName = name;
        }

        private void setId(int id) {
            mId = id;
        }

        private boolean isVisited() {
            return mVisited;
        }

        private void setParent(MtpObject parent) {
            mParent = parent;
        }

        private void setDir(boolean dir) {
            if (dir != mIsDir) {
                mIsDir = dir;
                mChildren = mIsDir ? new HashMap<>() : null;
            }
        }

        private void setVisited(boolean visited) {
            mVisited = visited;
        }

        private MtpObjectState getState() {
            return mState;
        }

        private void setState(MtpObjectState state) {
            mState = state;
            if (mState == MtpObjectState.NORMAL)
                mOp = MtpOperation.NONE;
        }

        private MtpOperation getOperation() {
            return mOp;
        }

        private void setOperation(MtpOperation op) {
            mOp = op;
        }

        private FileObserver getObserver() {
            return mObserver;
        }

        private void setObserver(FileObserver observer) {
            mObserver = observer;
        }

        private void addChild(MtpObject child) {
            mChildren.put(child.getName(), child);
        }

        private MtpObject getChild(String name) {
            return mChildren.get(name);
        }

        private Collection<MtpObject> getChildren() {
            return mChildren.values();
        }

        private boolean exists() {
            return getPath().toFile().exists();
        }

        private MtpObject copy(boolean recursive) {
            MtpObject copy = new MtpObject(mName, mId, mStorage, mParent, mIsDir);
            copy.mIsDir = mIsDir;
            copy.mVisited = mVisited;
            copy.mState = mState;
            copy.mChildren = mIsDir ? new HashMap<>() : null;
            if (recursive && mIsDir) {
                for (MtpObject child : mChildren.values()) {
                    MtpObject childCopy = child.copy(true);
                    childCopy.setParent(copy);
                    copy.addChild(childCopy);
                }
            }
            return copy;
        }
    }

    /**
     * A class that processes generated filesystem events.
     */
    public static abstract class MtpNotifier {
        /**
         * Called when an object is added.
         */
        public abstract void sendObjectAdded(int id);

        /**
         * Called when an object is deleted.
         */
        public abstract void sendObjectRemoved(int id);

        /**
         * Called when an object info is changed.
         */
        public abstract void sendObjectInfoChanged(int id);
    }

    private MtpNotifier mMtpNotifier;

    // A cache of MtpObjects. The objects in the cache are keyed by object id.
    // The root object of each storage isn't in this map since they all have ObjectId 0.
    // Instead, they can be found in mRoots keyed by storageId.
    private HashMap<Integer, MtpObject> mObjects;

    // A cache of the root MtpObject for each storage, keyed by storage id.
    private HashMap<Integer, MtpObject> mRoots;

    // Object and Storage ids are allocated incrementally and not to be reused.
    private int mNextObjectId;
    private int mNextStorageId;

    // Special subdirectories. When set, only return objects rooted in these directories, and do
    // not allow them to be modified.
    private Set<String> mSubdirectories;

    private volatile boolean mCheckConsistency;
    private Thread mConsistencyThread;

    public MtpStorageManager(MtpNotifier notifier, Set<String> subdirectories) {
        mMtpNotifier = notifier;
        mSubdirectories = subdirectories;
        mObjects = new HashMap<>();
        mRoots = new HashMap<>();
        mNextObjectId = 1;
        mNextStorageId = 1;

        mCheckConsistency = false; // Set to true to turn on automatic consistency checking
        mConsistencyThread = new Thread(() -> {
            while (mCheckConsistency) {
                try {
                    Thread.sleep(15 * 1000);
                } catch (InterruptedException e) {
                    return;
                }
                if (MtpStorageManager.this.checkConsistency()) {
                    Log.v(TAG, "Cache is consistent");
                } else {
                    Log.w(TAG, "Cache is not consistent");
                }
            }
        });
        if (mCheckConsistency)
            mConsistencyThread.start();
    }

    /**
     * Clean up resources used by the storage manager.
     */
    public synchronized void close() {
        for (MtpObject obj : mObjects.values()) {
            if (obj.getObserver() != null) {
                obj.getObserver().stopWatching();
                obj.setObserver(null);
            }
        }
        for (MtpObject obj : mRoots.values()) {
            if (obj.getObserver() != null) {
                obj.getObserver().stopWatching();
                obj.setObserver(null);
            }
        }

        // Shut down the consistency checking thread
        if (mCheckConsistency) {
            mCheckConsistency = false;
            mConsistencyThread.interrupt();
            try {
                mConsistencyThread.join();
            } catch (InterruptedException e) {
                // ignore
            }
        }
    }

    /**
     * Sets the special subdirectories, which are the subdirectories of root storage that queries
     * are restricted to. Must be done before any root storages are accessed.
     * @param subDirs Subdirectories to set, or null to reset.
     */
    public synchronized void setSubdirectories(Set<String> subDirs) {
        mSubdirectories = subDirs;
    }

    /**
     * Allocates an MTP storage id for the given volume and add it to current roots.
     * @param volume Storage to add.
     * @return the associated MtpStorage
     */
    public synchronized MtpStorage addMtpStorage(StorageVolume volume) {
        int storageId = ((getNextStorageId() & 0x0000FFFF) << 16) + 1;
        MtpStorage storage = new MtpStorage(volume, storageId);
        MtpObject root = new MtpObject(storage.getPath(), storageId, storage, null, true);
        mRoots.put(storageId, root);
        return storage;
    }

    /**
     * Removes the given storage and all associated items from the cache.
     * @param storage Storage to remove.
     */
    public synchronized void removeMtpStorage(MtpStorage storage) {
        removeObjectFromCache(getStorageRoot(storage.getStorageId()), true, true);
    }

    /**
     * Checks if the given object can be renamed, moved, or deleted.
     * If there are special subdirectories, they cannot be modified.
     * @param obj Object to check.
     * @return Whether object can be modified.
     */
    private synchronized boolean isSpecialSubDir(MtpObject obj) {
        return obj.getParent().isRoot() && mSubdirectories != null
                && !mSubdirectories.contains(obj.getName());
    }

    /**
     * Get the object with the specified path. Visit any necessary directories on the way.
     * @param path Full path of the object to find.
     * @return The desired object, or null if it cannot be found.
     */
    public synchronized MtpObject getByPath(String path) {
        MtpObject obj = null;
        for (MtpObject root : mRoots.values()) {
            if (path.startsWith(root.getName())) {
                obj = root;
                path = path.substring(root.getName().length());
            }
        }
        for (String name : path.split("/")) {
            if (obj == null || !obj.isDir())
                return null;
            if ("".equals(name))
                continue;
            if (!obj.isVisited())
                getChildren(obj);
            obj = obj.getChild(name);
        }
        return obj;
    }

    /**
     * Get the object with specified id.
     * @param id Id of object. must not be 0 or 0xFFFFFFFF
     * @return Object, or null if error.
     */
    public synchronized MtpObject getObject(int id) {
        if (id == 0 || id == 0xFFFFFFFF) {
            Log.w(TAG, "Can't get root storages with getObject()");
            return null;
        }
        if (!mObjects.containsKey(id)) {
            Log.w(TAG, "Id " + id + " doesn't exist");
            return null;
        }
        return mObjects.get(id);
    }

    /**
     * Get the storage with specified id.
     * @param id Storage id.
     * @return Object that is the root of the storage, or null if error.
     */
    public MtpObject getStorageRoot(int id) {
        if (!mRoots.containsKey(id)) {
            Log.w(TAG, "StorageId " + id + " doesn't exist");
            return null;
        }
        return mRoots.get(id);
    }

    private int getNextObjectId() {
        int ret = mNextObjectId;
        // Treat the id as unsigned int
        mNextObjectId = (int) ((long) mNextObjectId + 1);
        return ret;
    }

    private int getNextStorageId() {
        return mNextStorageId++;
    }

    /**
     * Get all objects matching the given parent, format, and storage
     * @param parent object id of the parent. 0 for all objects, 0xFFFFFFFF for all object in root
     * @param format format of returned objects. 0 for any format
     * @param storageId storage id to look in. 0xFFFFFFFF for all storages
     * @return A list of matched objects, or null if error
     */
    public synchronized List<MtpObject> getObjects(int parent, int format, int storageId) {
        boolean recursive = parent == 0;
        ArrayList<MtpObject> objs = new ArrayList<>();
        boolean ret = true;
        if (parent == 0xFFFFFFFF)
            parent = 0;
        if (storageId == 0xFFFFFFFF) {
            // query all stores
            if (parent == 0) {
                // Get the objects of this format and parent in each store.
                for (MtpObject root : mRoots.values()) {
                    ret &= getObjects(objs, root, format, recursive);
                }
                return ret ? objs : null;
            }
        }
        MtpObject obj = parent == 0 ? getStorageRoot(storageId) : getObject(parent);
        if (obj == null)
            return null;
        ret = getObjects(objs, obj, format, recursive);
        return ret ? objs : null;
    }

    private synchronized boolean getObjects(List<MtpObject> toAdd, MtpObject parent, int format, boolean rec) {
        Collection<MtpObject> children = getChildren(parent);
        if (children == null)
            return false;

        for (MtpObject o : children) {
            if (format == 0 || o.getFormat() == format) {
                toAdd.add(o);
            }
        }
        boolean ret = true;
        if (rec) {
            // Get all objects recursively.
            for (MtpObject o : children) {
                if (o.isDir())
                    ret &= getObjects(toAdd, o, format, true);
            }
        }
        return ret;
    }

    /**
     * Return the children of the given object. If the object hasn't been visited yet, add
     * its children to the cache and start observing it.
     * @param object the parent object
     * @return The collection of child objects or null if error
     */
    private synchronized Collection<MtpObject> getChildren(MtpObject object) {
        if (object == null || !object.isDir()) {
            Log.w(TAG, "Can't find children of " + (object == null ? "null" : object.getId()));
            return null;
        }
        if (!object.isVisited()) {
            Path dir = object.getPath();
            /*
             * If a file is added after the observer starts watching the directory, but before
             * the contents are listed, it will generate an event that will get processed
             * after this synchronized function returns. We handle this by ignoring object
             * added events if an object at that path already exists.
             */
            if (object.getObserver() != null)
                Log.e(TAG, "Observer is not null!");
            object.setObserver(new MtpObjectObserver(object));
            object.getObserver().startWatching();
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
                for (Path file : stream) {
                    addObjectToCache(object, file.getFileName().toString(),
                            file.toFile().isDirectory());
                }
            } catch (IOException | DirectoryIteratorException e) {
                Log.e(TAG, e.toString());
                object.getObserver().stopWatching();
                object.setObserver(null);
                return null;
            }
            object.setVisited(true);
        }
        return object.getChildren();
    }

    /**
     * Create a new object from the given path and add it to the cache.
     * @param parent The parent object
     * @param newName Path of the new object
     * @return the new object if success, else null
     */
    private synchronized MtpObject addObjectToCache(MtpObject parent, String newName,
            boolean isDir) {
        if (!parent.isRoot() && getObject(parent.getId()) != parent)
            // parent object has been removed
            return null;
        if (parent.getChild(newName) != null) {
            // Object already exists
            return null;
        }
        if (mSubdirectories != null && parent.isRoot() && !mSubdirectories.contains(newName)) {
            // Not one of the restricted subdirectories.
            return null;
        }

        MtpObject obj = new MtpObject(newName, getNextObjectId(), parent.mStorage, parent, isDir);
        mObjects.put(obj.getId(), obj);
        parent.addChild(obj);
        return obj;
    }

    /**
     * Remove the given path from the cache.
     * @param removed The removed object
     * @param removeGlobal Whether to remove the object from the global id map
     * @param recursive Whether to also remove its children recursively.
     * @return true if successfully removed
     */
    private synchronized boolean removeObjectFromCache(MtpObject removed, boolean removeGlobal,
            boolean recursive) {
        boolean ret = removed.isRoot()
                || removed.getParent().mChildren.remove(removed.getName(), removed);
        if (!ret && sDebug)
            Log.w(TAG, "Failed to remove from parent " + removed.getPath());
        if (removed.isRoot()) {
            ret = mRoots.remove(removed.getId(), removed) && ret;
        } else if (removeGlobal) {
            ret = mObjects.remove(removed.getId(), removed) && ret;
        }
        if (!ret && sDebug)
            Log.w(TAG, "Failed to remove from global cache " + removed.getPath());
        if (removed.getObserver() != null) {
            removed.getObserver().stopWatching();
            removed.setObserver(null);
        }
        if (removed.isDir() && recursive) {
            // Remove all descendants from cache recursively
            Collection<MtpObject> children = new ArrayList<>(removed.getChildren());
            for (MtpObject child : children) {
                ret = removeObjectFromCache(child, removeGlobal, true) && ret;
            }
        }
        return ret;
    }

    private synchronized void handleAddedObject(MtpObject parent, String path, boolean isDir) {
        MtpOperation op = MtpOperation.NONE;
        MtpObject obj = parent.getChild(path);
        if (obj != null) {
            MtpObjectState state = obj.getState();
            op = obj.getOperation();
            if (obj.isDir() != isDir && state != MtpObjectState.FROZEN_REMOVED)
                Log.d(TAG, "Inconsistent directory info! " + obj.getPath());
            obj.setDir(isDir);
            switch (state) {
                case FROZEN:
                case FROZEN_REMOVED:
                    obj.setState(MtpObjectState.FROZEN_ADDED);
                    break;
                case FROZEN_ONESHOT_ADD:
                    obj.setState(MtpObjectState.NORMAL);
                    break;
                case NORMAL:
                case FROZEN_ADDED:
                    // This can happen when handling listed object in a new directory.
                    return;
                default:
                    Log.w(TAG, "Unexpected state in add " + path + " " + state);
            }
            if (sDebug)
                Log.i(TAG, state + " transitioned to " + obj.getState() + " in op " + op);
        } else {
            obj = MtpStorageManager.this.addObjectToCache(parent, path, isDir);
            if (obj != null) {
                MtpStorageManager.this.mMtpNotifier.sendObjectAdded(obj.getId());
            } else {
                if (sDebug)
                    Log.w(TAG, "object " + path + " already exists");
                return;
            }
        }
        if (isDir) {
            // If this was added as part of a rename do not visit or send events.
            if (op == MtpOperation.RENAME)
                return;

            // If it was part of a copy operation, then only add observer if it was visited before.
            if (op == MtpOperation.COPY && !obj.isVisited())
                return;

            if (obj.getObserver() != null) {
                Log.e(TAG, "Observer is not null!");
                return;
            }
            obj.setObserver(new MtpObjectObserver(obj));
            obj.getObserver().startWatching();
            obj.setVisited(true);

            // It's possible that objects were added to a watched directory before the watch can be
            // created, so manually handle those.
            try (DirectoryStream<Path> stream = Files.newDirectoryStream(obj.getPath())) {
                for (Path file : stream) {
                    if (sDebug)
                        Log.i(TAG, "Manually handling event for " + file.getFileName().toString());
                    handleAddedObject(obj, file.getFileName().toString(),
                            file.toFile().isDirectory());
                }
            } catch (IOException | DirectoryIteratorException e) {
                Log.e(TAG, e.toString());
                obj.getObserver().stopWatching();
                obj.setObserver(null);
            }
        }
    }

    private synchronized void handleRemovedObject(MtpObject obj) {
        MtpObjectState state = obj.getState();
        MtpOperation op = obj.getOperation();
        switch (state) {
            case FROZEN_ADDED:
                obj.setState(MtpObjectState.FROZEN_REMOVED);
                break;
            case FROZEN_ONESHOT_DEL:
                removeObjectFromCache(obj, op != MtpOperation.RENAME, false);
                break;
            case FROZEN:
                obj.setState(MtpObjectState.FROZEN_REMOVED);
                break;
            case NORMAL:
                if (MtpStorageManager.this.removeObjectFromCache(obj, true, true))
                    MtpStorageManager.this.mMtpNotifier.sendObjectRemoved(obj.getId());
                break;
            default:
                // This shouldn't happen; states correspond to objects that don't exist
                Log.e(TAG, "Got unexpected object remove for " + obj.getName());
        }
        if (sDebug)
            Log.i(TAG, state + " transitioned to " + obj.getState() + " in op " + op);
    }

    private synchronized void handleChangedObject(MtpObject parent, String path) {
        MtpOperation op = MtpOperation.NONE;
        MtpObject obj = parent.getChild(path);
        if (obj != null) {
            // Only handle files for size change notification event
            if ((!obj.isDir()) && (obj.getSize() > 0))
            {
                MtpObjectState state = obj.getState();
                op = obj.getOperation();
                MtpStorageManager.this.mMtpNotifier.sendObjectInfoChanged(obj.getId());
                if (sDebug)
                    Log.d(TAG, "sendObjectInfoChanged: id=" + obj.getId() + ",size=" + obj.getSize());
            }
        } else {
            if (sDebug)
                Log.w(TAG, "object " + path + " null");
        }
    }

    /**
     * Block the caller until all events currently in the event queue have been
     * read and processed. Used for testing purposes.
     */
    public void flushEvents() {
        try {
            // TODO make this smarter
            Thread.sleep(500);
        } catch (InterruptedException e) {

        }
    }

    /**
     * Dumps a representation of the cache to log.
     */
    public synchronized void dump() {
        for (int key : mObjects.keySet()) {
            MtpObject obj = mObjects.get(key);
            Log.i(TAG, key + " | " + (obj.getParent() == null ? obj.getParent().getId() : "null")
                    + " | " + obj.getName() + " | " + (obj.isDir() ? "dir" : "obj")
                    + " | " + (obj.isVisited() ? "v" : "nv") + " | " + obj.getState());
        }
    }

    /**
     * Checks consistency of the cache. This checks whether all objects have correct links
     * to their parent, and whether directories are missing or have extraneous objects.
     * @return true iff cache is consistent
     */
    public synchronized boolean checkConsistency() {
        List<MtpObject> objs = new ArrayList<>();
        objs.addAll(mRoots.values());
        objs.addAll(mObjects.values());
        boolean ret = true;
        for (MtpObject obj : objs) {
            if (!obj.exists()) {
                Log.w(TAG, "Object doesn't exist " + obj.getPath() + " " + obj.getId());
                ret = false;
            }
            if (obj.getState() != MtpObjectState.NORMAL) {
                Log.w(TAG, "Object " + obj.getPath() + " in state " + obj.getState());
                ret = false;
            }
            if (obj.getOperation() != MtpOperation.NONE) {
                Log.w(TAG, "Object " + obj.getPath() + " in operation " + obj.getOperation());
                ret = false;
            }
            if (!obj.isRoot() && mObjects.get(obj.getId()) != obj) {
                Log.w(TAG, "Object " + obj.getPath() + " is not in map correctly");
                ret = false;
            }
            if (obj.getParent() != null) {
                if (obj.getParent().isRoot() && obj.getParent()
                        != mRoots.get(obj.getParent().getId())) {
                    Log.w(TAG, "Root parent is not in root mapping " + obj.getPath());
                    ret = false;
                }
                if (!obj.getParent().isRoot() && obj.getParent()
                        != mObjects.get(obj.getParent().getId())) {
                    Log.w(TAG, "Parent is not in object mapping " + obj.getPath());
                    ret = false;
                }
                if (obj.getParent().getChild(obj.getName()) != obj) {
                    Log.w(TAG, "Child does not exist in parent " + obj.getPath());
                    ret = false;
                }
            }
            if (obj.isDir()) {
                if (obj.isVisited() == (obj.getObserver() == null)) {
                    Log.w(TAG, obj.getPath() + " is " + (obj.isVisited() ? "" : "not ")
                            + " visited but observer is " + obj.getObserver());
                    ret = false;
                }
                if (!obj.isVisited() && obj.getChildren().size() > 0) {
                    Log.w(TAG, obj.getPath() + " is not visited but has children");
                    ret = false;
                }
                try (DirectoryStream<Path> stream = Files.newDirectoryStream(obj.getPath())) {
                    Set<String> files = new HashSet<>();
                    for (Path file : stream) {
                        if (obj.isVisited() &&
                                obj.getChild(file.getFileName().toString()) == null &&
                                (mSubdirectories == null || !obj.isRoot() ||
                                        mSubdirectories.contains(file.getFileName().toString()))) {
                            Log.w(TAG, "File exists in fs but not in children " + file);
                            ret = false;
                        }
                        files.add(file.toString());
                    }
                    for (MtpObject child : obj.getChildren()) {
                        if (!files.contains(child.getPath().toString())) {
                            Log.w(TAG, "File in children doesn't exist in fs " + child.getPath());
                            ret = false;
                        }
                        if (child != mObjects.get(child.getId())) {
                            Log.w(TAG, "Child is not in object map " + child.getPath());
                            ret = false;
                        }
                    }
                } catch (IOException | DirectoryIteratorException e) {
                    Log.w(TAG, e.toString());
                    ret = false;
                }
            }
        }
        return ret;
    }

    /**
     * Informs MtpStorageManager that an object with the given path is about to be added.
     * @param parent The parent object of the object to be added.
     * @param name Filename of object to add.
     * @return Object id of the added object, or -1 if it cannot be added.
     */
    public synchronized int beginSendObject(MtpObject parent, String name, int format) {
        if (sDebug)
            Log.v(TAG, "beginSendObject " + name);
        if (!parent.isDir())
            return -1;
        if (parent.isRoot() && mSubdirectories != null && !mSubdirectories.contains(name))
            return -1;
        getChildren(parent); // Ensure parent is visited
        MtpObject obj  = addObjectToCache(parent, name, format == MtpConstants.FORMAT_ASSOCIATION);
        if (obj == null)
            return -1;
        obj.setState(MtpObjectState.FROZEN);
        obj.setOperation(MtpOperation.ADD);
        return obj.getId();
    }

    /**
     * Clean up the object state after a sendObject operation.
     * @param obj The object, returned from beginAddObject().
     * @param succeeded Whether the file was successfully created.
     * @return Whether cache state was successfully cleaned up.
     */
    public synchronized boolean endSendObject(MtpObject obj, boolean succeeded) {
        if (sDebug)
            Log.v(TAG, "endSendObject " + succeeded);
        return generalEndAddObject(obj, succeeded, true);
    }

    /**
     * Informs MtpStorageManager that the given object is about to be renamed.
     * If this returns true, it must be followed with an endRenameObject()
     * @param obj Object to be renamed.
     * @param newName New name of the object.
     * @return Whether renaming is allowed.
     */
    public synchronized boolean beginRenameObject(MtpObject obj, String newName) {
        if (sDebug)
            Log.v(TAG, "beginRenameObject " + obj.getName() + " " + newName);
        if (obj.isRoot())
            return false;
        if (isSpecialSubDir(obj))
            return false;
        if (obj.getParent().getChild(newName) != null)
            // Object already exists in parent with that name.
            return false;

        MtpObject oldObj = obj.copy(false);
        obj.setName(newName);
        obj.getParent().addChild(obj);
        oldObj.getParent().addChild(oldObj);
        return generalBeginRenameObject(oldObj, obj);
    }

    /**
     * Cleans up cache state after a rename operation and sends any events that were missed.
     * @param obj The object being renamed, the same one that was passed in beginRenameObject().
     * @param oldName The previous name of the object.
     * @param success Whether the rename operation succeeded.
     * @return Whether state was successfully cleaned up.
     */
    public synchronized boolean endRenameObject(MtpObject obj, String oldName, boolean success) {
        if (sDebug)
            Log.v(TAG, "endRenameObject " + success);
        MtpObject parent = obj.getParent();
        MtpObject oldObj = parent.getChild(oldName);
        if (!success) {
            // If the rename failed, we want oldObj to be the original and obj to be the dummy.
            // Switch the objects, except for their name and state.
            MtpObject temp = oldObj;
            MtpObjectState oldState = oldObj.getState();
            temp.setName(obj.getName());
            temp.setState(obj.getState());
            oldObj = obj;
            oldObj.setName(oldName);
            oldObj.setState(oldState);
            obj = temp;
            parent.addChild(obj);
            parent.addChild(oldObj);
        }
        return generalEndRenameObject(oldObj, obj, success);
    }

    /**
     * Informs MtpStorageManager that the given object is about to be deleted by the initiator,
     * so don't send an event.
     * @param obj Object to be deleted.
     * @return Whether cache deletion is allowed.
     */
    public synchronized boolean beginRemoveObject(MtpObject obj) {
        if (sDebug)
            Log.v(TAG, "beginRemoveObject " + obj.getName());
        return !obj.isRoot() && !isSpecialSubDir(obj)
                && generalBeginRemoveObject(obj, MtpOperation.DELETE);
    }

    /**
     * Clean up cache state after a delete operation and send any events that were missed.
     * @param obj Object to be deleted, same one passed in beginRemoveObject().
     * @param success Whether operation was completed successfully.
     * @return Whether cache state is correct.
     */
    public synchronized boolean endRemoveObject(MtpObject obj, boolean success) {
        if (sDebug)
            Log.v(TAG, "endRemoveObject " + success);
        boolean ret = true;
        if (obj.isDir()) {
            for (MtpObject child : new ArrayList<>(obj.getChildren()))
                if (child.getOperation() == MtpOperation.DELETE)
                    ret = endRemoveObject(child, success) && ret;
        }
        return generalEndRemoveObject(obj, success, true) && ret;
    }

    /**
     * Informs MtpStorageManager that the given object is about to be moved to a new parent.
     * @param obj Object to be moved.
     * @param newParent The new parent object.
     * @return Whether the move is allowed.
     */
    public synchronized boolean beginMoveObject(MtpObject obj, MtpObject newParent) {
        if (sDebug)
            Log.v(TAG, "beginMoveObject " + newParent.getPath());
        if (obj.isRoot())
            return false;
        if (isSpecialSubDir(obj))
            return false;
        getChildren(newParent); // Ensure parent is visited
        if (newParent.getChild(obj.getName()) != null)
            // Object already exists in parent with that name.
            return false;
        if (obj.getStorageId() != newParent.getStorageId()) {
            /*
             * The move is occurring across storages. The observers will not remain functional
             * after the move, and the move will not be atomic. We have to copy the file tree
             * to the destination and recreate the observers once copy is complete.
             */
            MtpObject newObj = obj.copy(true);
            newObj.setParent(newParent);
            newParent.addChild(newObj);
            return generalBeginRemoveObject(obj, MtpOperation.RENAME)
                    && generalBeginCopyObject(newObj, false);
        }
        // Move obj to new parent, create a dummy object in the old parent.
        MtpObject oldObj = obj.copy(false);
        obj.setParent(newParent);
        oldObj.getParent().addChild(oldObj);
        obj.getParent().addChild(obj);
        return generalBeginRenameObject(oldObj, obj);
    }

    /**
     * Clean up cache state after a move operation and send any events that were missed.
     * @param oldParent The old parent object.
     * @param newParent The new parent object.
     * @param name The name of the object being moved.
     * @param success Whether operation was completed successfully.
     * @return Whether cache state is correct.
     */
    public synchronized boolean endMoveObject(MtpObject oldParent, MtpObject newParent, String name,
            boolean success) {
        if (sDebug)
            Log.v(TAG, "endMoveObject " + success);
        MtpObject oldObj = oldParent.getChild(name);
        MtpObject newObj = newParent.getChild(name);
        if (oldObj == null || newObj == null)
            return false;
        if (oldParent.getStorageId() != newObj.getStorageId()) {
            boolean ret = endRemoveObject(oldObj, success);
            return generalEndCopyObject(newObj, success, true) && ret;
        }
        if (!success) {
            // If the rename failed, we want oldObj to be the original and obj to be the dummy.
            // Switch the objects, except for their parent and state.
            MtpObject temp = oldObj;
            MtpObjectState oldState = oldObj.getState();
            temp.setParent(newObj.getParent());
            temp.setState(newObj.getState());
            oldObj = newObj;
            oldObj.setParent(oldParent);
            oldObj.setState(oldState);
            newObj = temp;
            newObj.getParent().addChild(newObj);
            oldParent.addChild(oldObj);
        }
        return generalEndRenameObject(oldObj, newObj, success);
    }

    /**
     * Informs MtpStorageManager that the given object is about to be copied recursively.
     * @param object Object to be copied
     * @param newParent New parent for the object.
     * @return The object id for the new copy, or -1 if error.
     */
    public synchronized int beginCopyObject(MtpObject object, MtpObject newParent) {
        if (sDebug)
            Log.v(TAG, "beginCopyObject " + object.getName() + " to " + newParent.getPath());
        String name = object.getName();
        if (!newParent.isDir())
            return -1;
        if (newParent.isRoot() && mSubdirectories != null && !mSubdirectories.contains(name))
            return -1;
        getChildren(newParent); // Ensure parent is visited
        if (newParent.getChild(name) != null)
            return -1;
        MtpObject newObj  = object.copy(object.isDir());
        newParent.addChild(newObj);
        newObj.setParent(newParent);
        if (!generalBeginCopyObject(newObj, true))
            return -1;
        return newObj.getId();
    }

    /**
     * Cleans up cache state after a copy operation.
     * @param object Object that was copied.
     * @param success Whether the operation was successful.
     * @return Whether cache state is consistent.
     */
    public synchronized boolean endCopyObject(MtpObject object, boolean success) {
        if (sDebug)
            Log.v(TAG, "endCopyObject " + object.getName() + " " + success);
        return generalEndCopyObject(object, success, false);
    }

    private synchronized boolean generalEndAddObject(MtpObject obj, boolean succeeded,
            boolean removeGlobal) {
        switch (obj.getState()) {
            case FROZEN:
                // Object was never created.
                if (succeeded) {
                    // The operation was successful so the event must still be in the queue.
                    obj.setState(MtpObjectState.FROZEN_ONESHOT_ADD);
                } else {
                    // The operation failed and never created the file.
                    if (!removeObjectFromCache(obj, removeGlobal, false)) {
                        return false;
                    }
                }
                break;
            case FROZEN_ADDED:
                obj.setState(MtpObjectState.NORMAL);
                if (!succeeded) {
                    MtpObject parent = obj.getParent();
                    // The operation failed but some other process created the file. Send an event.
                    if (!removeObjectFromCache(obj, removeGlobal, false))
                        return false;
                    handleAddedObject(parent, obj.getName(), obj.isDir());
                }
                // else: The operation successfully created the object.
                break;
            case FROZEN_REMOVED:
                if (!removeObjectFromCache(obj, removeGlobal, false))
                    return false;
                if (succeeded) {
                    // Some other process deleted the object. Send an event.
                    mMtpNotifier.sendObjectRemoved(obj.getId());
                }
                // else: Mtp deleted the object as part of cleanup. Don't send an event.
                break;
            default:
                return false;
        }
        return true;
    }

    private synchronized boolean generalEndRemoveObject(MtpObject obj, boolean success,
            boolean removeGlobal) {
        switch (obj.getState()) {
            case FROZEN:
                if (success) {
                    // Object was deleted successfully, and event is still in the queue.
                    obj.setState(MtpObjectState.FROZEN_ONESHOT_DEL);
                } else {
                    // Object was not deleted.
                    obj.setState(MtpObjectState.NORMAL);
                }
                break;
            case FROZEN_ADDED:
                // Object was deleted, and then readded.
                obj.setState(MtpObjectState.NORMAL);
                if (success) {
                    // Some other process readded the object.
                    MtpObject parent = obj.getParent();
                    if (!removeObjectFromCache(obj, removeGlobal, false))
                        return false;
                    handleAddedObject(parent, obj.getName(), obj.isDir());
                }
                // else : Object still exists after failure.
                break;
            case FROZEN_REMOVED:
                if (!removeObjectFromCache(obj, removeGlobal, false))
                    return false;
                if (!success) {
                    // Some other process deleted the object.
                    mMtpNotifier.sendObjectRemoved(obj.getId());
                }
                // else : This process deleted the object as part of the operation.
                break;
            default:
                return false;
        }
        return true;
    }

    private synchronized boolean generalBeginRenameObject(MtpObject fromObj, MtpObject toObj) {
        fromObj.setState(MtpObjectState.FROZEN);
        toObj.setState(MtpObjectState.FROZEN);
        fromObj.setOperation(MtpOperation.RENAME);
        toObj.setOperation(MtpOperation.RENAME);
        return true;
    }

    private synchronized boolean generalEndRenameObject(MtpObject fromObj, MtpObject toObj,
            boolean success) {
        boolean ret = generalEndRemoveObject(fromObj, success, !success);
        return generalEndAddObject(toObj, success, success) && ret;
    }

    private synchronized boolean generalBeginRemoveObject(MtpObject obj, MtpOperation op) {
        obj.setState(MtpObjectState.FROZEN);
        obj.setOperation(op);
        if (obj.isDir()) {
            for (MtpObject child : obj.getChildren())
                generalBeginRemoveObject(child, op);
        }
        return true;
    }

    private synchronized boolean generalBeginCopyObject(MtpObject obj, boolean newId) {
        obj.setState(MtpObjectState.FROZEN);
        obj.setOperation(MtpOperation.COPY);
        if (newId) {
            obj.setId(getNextObjectId());
            mObjects.put(obj.getId(), obj);
        }
        if (obj.isDir())
            for (MtpObject child : obj.getChildren())
                if (!generalBeginCopyObject(child, newId))
                    return false;
        return true;
    }

    private synchronized boolean generalEndCopyObject(MtpObject obj, boolean success, boolean addGlobal) {
        if (success && addGlobal)
            mObjects.put(obj.getId(), obj);
        boolean ret = true;
        if (obj.isDir()) {
            for (MtpObject child : new ArrayList<>(obj.getChildren())) {
                if (child.getOperation() == MtpOperation.COPY)
                    ret = generalEndCopyObject(child, success, addGlobal) && ret;
            }
        }
        ret = generalEndAddObject(obj, success, success || !addGlobal) && ret;
        return ret;
    }
}
