// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.components.minidump_uploader;

import android.support.annotation.Nullable;

import org.chromium.base.Log;
import org.chromium.base.VisibleForTesting;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * The CrashFileManager is responsible for managing the "Crash Reports" directory containing
 * minidump files and shepherding them through a state machine represented by the file names.
 *  1. Minidumps are read from Crashpad's CrashReportDatabase and re-written as MIME files in the
 *     "Crash Reports" directory as foo.dmpNNNNN where NNNNN is the PID (process id) of the
 *     crashing process.
 *  2. foo.dmpNNNNN.try0 is a minidump file with recent logcat output attached to it; or a file for
 *     which logcat output has been intentionally omitted. Notably, Webview-generated minidumps do
 *     not include logcat output.
 *  3. foo.dmpNNNNN.tryM for M > 0 is a minidump file that's been attempted to be uploaded to the
 *     crash server, but for which M upload attempts have failed.
 *  4. foo.upNNNNN.tryM names a successfully uploaded file.
 *  5. foo.skippedNNNNN.tryM names for a file whose upload was skipped. An upload may be skipped,
 *     for example, if the user has not consented to uploading crash reports. These files are marked
 *     as skipped rather than deleted immediately to allow the user to manually initiate an upload.
 *  6. foo.forcedNNNNN.tryM names a file that the user has manually requested to upload.
 *  7. foo.tmp is a temporary file.
 */
public class CrashFileManager {
    private static final String TAG = "CrashFileManager";

    /**
     * The name of the crash directory.
     */
    public static final String CRASH_DUMP_DIR = "Crash Reports";

    private static final String CRASHPAD_DIR = "Crashpad";

    // This should mirror the C++ CrashUploadList::kReporterLogFilename variable.
    @VisibleForTesting
    public static final String CRASH_DUMP_LOGFILE = "uploads.log";

    // Unlike the MINIDUMP_READY_FOR_UPLOAD_PATTERN below, this pattern omits a ".tryN" suffix.
    private static final Pattern MINIDUMP_SANS_LOGCAT_PATTERN =
            Pattern.compile("\\.dmp([0-9]*)\\z");

    private static final Pattern MINIDUMP_READY_FOR_UPLOAD_PATTERN =
            Pattern.compile("\\.(dmp|forced)([0-9]*)(\\.try([0-9]+))\\z");

    private static final Pattern UPLOADED_MINIDUMP_PATTERN =
            Pattern.compile("\\.up([0-9]*)(\\.try([0-9]+))\\z");

    private static final String NOT_YET_UPLOADED_MINIDUMP_SUFFIX = ".dmp";

    private static final String UPLOADED_MINIDUMP_SUFFIX = ".up";

    private static final String UPLOAD_SKIPPED_MINIDUMP_SUFFIX = ".skipped";

    private static final String UPLOAD_FORCED_MINIDUMP_SUFFIX = ".forced";

    private static final String UPLOAD_ATTEMPT_DELIMITER = ".try";

    // The suffix used when a minidump is first ready for upload: ".try0".
    public static final String READY_FOR_UPLOAD_SUFFIX = UPLOAD_ATTEMPT_DELIMITER + "0";

    // A delimiter between uid and the rest of a minidump filename. Only used for WebView minidumps.
    private static final String UID_DELIMITER = "_";

    @VisibleForTesting
    protected static final String TMP_SUFFIX = ".tmp";

    private static final Pattern TMP_PATTERN = Pattern.compile("\\.tmp\\z");

    // The maximum number of non-uploaded crashes that may be kept in the crash reports directory.
    // Chosen to attempt to balance between keeping a generous number of crashes, and not using up
    // too much filesystem storage space for obsolete crash reports.
    @VisibleForTesting
    protected static final int MAX_CRASH_REPORTS_TO_KEEP = 10;

    // The maximum age, in days, considered acceptable for a crash report. Reports older than this
    // age will be removed. The constant is chosen to be quite conservative, while still allowing
    // users to eventually reclaim filesystem storage space from obsolete crash reports.
    private static final int MAX_CRASH_REPORT_AGE_IN_DAYS = 30;

    // The maximum number of non-uploaded crashes to copy to the crash reports directory. The
    // difference between this value and MAX_CRASH_REPORTS_TO_KEEP is that TO_KEEP is only checked
    // when we clean out the crash directory - the TO_UPLOAD value is checked every time we try to
    // copy a minidump - to ensure we don't store too many minidumps before they are cleaned out
    // after being uploaded.
    @VisibleForTesting
    static final int MAX_CRASH_REPORTS_TO_UPLOAD = MAX_CRASH_REPORTS_TO_KEEP * 2;
    // Same as above except this value is enforced per UID, so that one single app can't hog all
    // storage/uploading resources.
    @VisibleForTesting
    static final int MAX_CRASH_REPORTS_TO_UPLOAD_PER_UID = MAX_CRASH_REPORTS_TO_KEEP;

    /**
     * Comparator used for sorting files by modification date.
     * @return Comparator for prioritizing the more recently modified file
     */
    @VisibleForTesting
    protected static final Comparator<File> sFileComparator = new Comparator<File>() {
        @Override
        public int compare(File lhs, File rhs) {
            if (lhs.lastModified() == rhs.lastModified()) {
                return lhs.compareTo(rhs);
            } else if (lhs.lastModified() < rhs.lastModified()) {
                return 1;
            } else {
                return -1;
            }
        }
    };

    /**
     * Delete the file {@param fileToDelete}.
     */
    public static boolean deleteFile(File fileToDelete) {
        boolean isSuccess = fileToDelete.delete();
        if (!isSuccess) {
            Log.w(TAG, "Unable to delete " + fileToDelete.getAbsolutePath());
        }
        return isSuccess;
    }

    /**
     * Returns whether a minidump file definitely lacks logcat output. Note: This method does not
     * provide an "if and only if" test: it may return false for a path that lacks logcat output, if
     * logcat output has been intentionally skipped for that minidump. However, a return value of
     * true means that the file definitely lacks logcat output.
     * @param path The minidump pathname to test.
     * @return Whether the given path corresponds to a minidump file that definitely lacks logcat
     *    output.
     */
    public static boolean isMinidumpSansLogcat(String path) {
        return MINIDUMP_SANS_LOGCAT_PATTERN.matcher(path).find();
    }

    public static String tryIncrementAttemptNumber(File mFileToUpload) {
        String newName = filenameWithIncrementedAttemptNumber(mFileToUpload.getPath());
        return mFileToUpload.renameTo(new File(newName)) ? newName : null;
    }

    /**
     * @return The file name to rename to after an addition attempt to upload
     */
    @VisibleForTesting
    public static String filenameWithIncrementedAttemptNumber(String filename) {
        int numTried = readAttemptNumberInternal(filename);
        if (numTried >= 0) {
            int newCount = numTried + 1;
            return filename.replace(
                    UPLOAD_ATTEMPT_DELIMITER + numTried, UPLOAD_ATTEMPT_DELIMITER + newCount);
        } else {
            // readAttemptNumberInternal returning -1 means there is no UPLOAD_ATTEMPT_DELIMITER in
            // the file name (or that there is a delimiter but no attempt number). So, we have to
            // add the delimiter and attempt number ourselves.
            return filename + UPLOAD_ATTEMPT_DELIMITER + "1";
        }
    }

    /**
     * Attempts to rename the given file to mark it as ready for upload. This should be done when
     * logcat extraction fails or is otherwise intentionally skipped. An equivalent operation is
     * done when extraction succeeds; but since the logcat output needs to be included in the
     * uploaded data, more than a simple rename is needed.
     *
     * @return The renamed file, or null if renaming failed.
     */
    public static File trySetReadyForUpload(File fileToUpload) {
        assert CrashFileManager.isMinidumpSansLogcat(fileToUpload.getName());
        File renamedFile = new File(fileToUpload.getPath() + READY_FOR_UPLOAD_SUFFIX);
        return fileToUpload.renameTo(renamedFile) ? renamedFile : null;
    }

    /**
     * Attempts to rename the given file to mark it as a forced upload. This is useful for allowing
     * users to manually initiate previously skipped uploads.
     *
     * @return The renamed file, or null if renaming failed.
     */
    public static File trySetForcedUpload(File fileToUpload) {
        if (fileToUpload.getName().contains(UPLOADED_MINIDUMP_SUFFIX)) {
            Log.w(TAG, "Refusing to reset upload attempt state for a file that has already been "
                            + "successfully uploaded: " + fileToUpload.getName());
            return null;
        }
        File renamedFile = new File(filenameWithForcedUploadState(fileToUpload.getPath()));
        return fileToUpload.renameTo(renamedFile) ? renamedFile : null;
    }

    /**
     * @return True iff the provided File was manually forced (by the user) to be uploaded.
     */
    public static boolean isForcedUpload(File fileToUpload) {
        return fileToUpload.getName().contains(UPLOAD_FORCED_MINIDUMP_SUFFIX);
    }

    /**
     * @return The filename to rename to so as to manually force an upload (including clearing any
     *     previous upload attempt history).
     */
    @VisibleForTesting
    protected static String filenameWithForcedUploadState(String filename) {
        int numTried = readAttemptNumber(filename);
        if (numTried > 0) {
            filename = filename.replace(
                    UPLOAD_ATTEMPT_DELIMITER + numTried, UPLOAD_ATTEMPT_DELIMITER + 0);
        }
        filename = filename.replace(UPLOAD_SKIPPED_MINIDUMP_SUFFIX, UPLOAD_FORCED_MINIDUMP_SUFFIX);
        return filename.replace(NOT_YET_UPLOADED_MINIDUMP_SUFFIX, UPLOAD_FORCED_MINIDUMP_SUFFIX);
    }

    /**
     * Returns how many times we've tried to upload a certain minidump file.
     * @return The number of attempts to upload the given minidump file, parsed from its filename.
     *     Returns 0 if an attempt number cannot be parsed from the filename.
     */
    public static int readAttemptNumber(String filename) {
        int numTries = readAttemptNumberInternal(filename);
        return numTries >= 0 ? numTries : 0;
    }

    /**
     * Returns how many times we've tried to upload a certain minidump file.
     * @return The number of attempts to upload the given minidump file, parsed from its filename,
     *     Returns -1 if an attempt number cannot be parsed from the filename.
     */
    @VisibleForTesting
    static int readAttemptNumberInternal(String filename) {
        int tryIndex = filename.lastIndexOf(UPLOAD_ATTEMPT_DELIMITER);
        if (tryIndex >= 0) {
            tryIndex += UPLOAD_ATTEMPT_DELIMITER.length();
            String numTriesString = filename.substring(tryIndex);
            Scanner numTriesScanner = new Scanner(numTriesString).useDelimiter("[^0-9]+");
            try {
                int nextInt = numTriesScanner.nextInt();
                // Only return the number if it occurs just after the UPLOAD_ATTEMPT_DELIMITER.
                return numTriesString.indexOf(Integer.toString(nextInt)) == 0 ? nextInt : -1;
            } catch (NoSuchElementException e) {
                return -1;
            }
        }
        return -1;
    }

    /**
     * Marks a crash dump file as successfully uploaded, by renaming the file.
     *
     * Does not immediately delete the file, for testing reasons. However, if renaming fails,
     * attempts to delete the file immediately.
     */
    public static void markUploadSuccess(File crashDumpFile) {
        CrashFileManager.renameCrashDumpFollowingUpload(crashDumpFile, UPLOADED_MINIDUMP_SUFFIX);
    }

    /**
     * Marks a crash dump file's upload being skipped. An upload might be skipped due to lack of
     * user consent, or due to this client being excluded from the sample of clients reporting
     * crashes.
     *
     * Renames the file rather than deleting it, so that the user can manually upload the file later
     * (via chrome://crashes). However, if renaming fails, attempts to delete the file immediately.
     */
    public static void markUploadSkipped(File crashDumpFile) {
        CrashFileManager.renameCrashDumpFollowingUpload(
                crashDumpFile, UPLOAD_SKIPPED_MINIDUMP_SUFFIX);
    }

    /**
     * Renames a crash dump file. However, if renaming fails, attempts to delete the file
     * immediately.
     */
    private static void renameCrashDumpFollowingUpload(File crashDumpFile, String suffix) {
        // The pre-upload filename might have been either "foo.dmpN.tryM" or "foo.forcedN.tryM".
        String newName = crashDumpFile.getPath()
                                 .replace(NOT_YET_UPLOADED_MINIDUMP_SUFFIX, suffix)
                                 .replace(UPLOAD_FORCED_MINIDUMP_SUFFIX, suffix);
        boolean renamed = crashDumpFile.renameTo(new File(newName));
        if (!renamed) {
            Log.w(TAG, "Failed to rename " + crashDumpFile);
            if (!crashDumpFile.delete()) {
                Log.w(TAG, "Failed to delete " + crashDumpFile);
            }
        }
    }

    private final File mCacheDir;

    public CrashFileManager(File cacheDir) {
        if (cacheDir == null) {
            throw new NullPointerException("Specified context cannot be null.");
        } else if (!cacheDir.isDirectory()) {
            throw new IllegalArgumentException(cacheDir.getAbsolutePath() + " is not a directory.");
        }
        mCacheDir = cacheDir;
    }

    /**
     * Create the crash directory for this file manager unless it exists already.
     * @return true iff the crash directory exists when this method returns.
     */
    private boolean ensureCrashDirExists() {
        File crashDir = getCrashDirectory();
        // Call mkdir before isDirectory to ensure that if another thread created the directory
        // just before the call to mkdir, the current thread fails mkdir, but passes isDirectory.
        return crashDir.mkdir() || crashDir.isDirectory();
    }

    /**
     * @return whether the crash directory already exists.
     */
    public boolean crashDirectoryExists() {
        return getCrashDirectory().isDirectory();
    }

    /**
     * Imports minidumps from Crashpad's database to the Crash Reports directory, converting them to
     * MIME files.
     **/
    private void importCrashpadMinidumps() {
        File crashpadDir = getCrashpadDirectory();
        if (crashpadDir.exists() && ensureCrashDirExists()) {
            File crashDir = getCrashDirectory();
            CrashReportMimeWriter.rewriteMinidumpsAsMIMEs(crashpadDir, crashDir);
        }
    }

    /**
     * Returns the most recent minidump without a logcat for a given pid, or null if no such
     * minidump exists. This method begins by reading all minidumps from Crashpad's database and
     * rewriting them as MIME files in the Crash Reports directory.
     */
    public File getMinidumpSansLogcatForPid(int pid) {
        importCrashpadMinidumps();
        File[] foundFiles = listCrashFiles(
            Pattern.compile("\\.dmp" + Integer.toString(pid) + "\\z"));
        return foundFiles.length > 0 ? foundFiles[0] : null;
    }

    /**
     * Returns all minidump files that definitely do not have logcat output, sorted by modification
     * time stamp. This method begins by reading all minidumps from Crashpad's database and
     * rewriting them as MIME files in the Crash Reports directory. Note: This method does not
     * provide an "if and only if" test: it may return omit some files that lack logcat output, if
     * logcat output has been intentionally skipped for those minidumps. However, any files returned
     * definitely lack logcat output.
     */
    public File[] getMinidumpsSansLogcat() {
        importCrashpadMinidumps();
        return listCrashFiles(MINIDUMP_SANS_LOGCAT_PATTERN);
    }

    /**
     * Returns all minidump files that could still be uploaded, sorted by modification time stamp.
     * Only returns files that we have tried to upload less than {@param maxTries} number of times.
     */
    public File[] getMinidumpsReadyForUpload(int maxTries) {
        return getFilesBelowMaxTries(listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN), maxTries);
    }

    /**
     * Returns all minidump files with the uid {@param uid} from {@param minidumpFiles}.
     */
    public static List<File> filterMinidumpFilesOnUid(File[] minidumpFiles, int uid) {
        List<File> uidMinidumps = new ArrayList<>();
        for (File minidump : minidumpFiles) {
            if (belongsToUid(minidump, uid)) {
                uidMinidumps.add(minidump);
            }
        }
        return uidMinidumps;
    }

    public void cleanOutAllNonFreshMinidumpFiles() {
        for (File f : getAllUploadedFiles()) {
            deleteFile(f);
        }
        for (File f : getAllTempFiles()) {
            deleteFile(f);
        }

        int numSavedCrashes = 0;
        for (File f : listCrashFiles(null)) {
            // The uploads.log file should always be preserved, as it stores the metadata that
            // powers the chrome://crashes UI.
            if (f.getName().equals(CRASH_DUMP_LOGFILE)) {
                continue;
            }

            // Delete any crash reports that are especially old.
            long ageInMillis = new Date().getTime() - f.lastModified();
            long ageInDays = TimeUnit.DAYS.convert(ageInMillis, TimeUnit.MILLISECONDS);
            if (ageInDays > MAX_CRASH_REPORT_AGE_IN_DAYS) {
                deleteFile(f);
                continue;
            }

            // Delete the oldest crash reports that exceed the cap on the number of allowed reports.
            if (numSavedCrashes < MAX_CRASH_REPORTS_TO_KEEP) {
                // Note that /not/ deleting the file is a no-op, so all that's needed is to mark
                // that one more file has been kept.
                ++numSavedCrashes;
            } else {
                deleteFile(f);
            }
        }
    }

    /**
     * Filters a set of files to keep the ones we have tried to upload only a few times.
     * Given a set of files {@param unfilteredFiles}, returns only the files in that set which we
     * have tried to upload less than {@param maxTries} times.
     */
    @VisibleForTesting
    static File[] getFilesBelowMaxTries(File[] unfilteredFiles, int maxTries) {
        List<File> filesBelowMaxTries = new ArrayList<>();
        for (File file : unfilteredFiles) {
            if (readAttemptNumber(file.getName()) < maxTries) {
                filesBelowMaxTries.add(file);
            }
        }
        return filesBelowMaxTries.toArray(new File[filesBelowMaxTries.size()]);
    }

    /**
     * Returns a sorted and filtered list of files within the crash directory.
     */
    @VisibleForTesting
    File[] listCrashFiles(@Nullable final Pattern pattern) {
        File crashDir = getCrashDirectory();

        FilenameFilter filter = null;
        if (pattern != null) {
            filter = new FilenameFilter() {
                @Override
                public boolean accept(File dir, String filename) {
                    return pattern.matcher(filename).find();
                }
            };
        }
        File[] foundFiles = crashDir.listFiles(filter);
        if (foundFiles == null) {
            Log.w(TAG, crashDir.getAbsolutePath() + " does not exist or is not a directory");
            return new File[] {};
        }
        Arrays.sort(foundFiles, sFileComparator);
        return foundFiles;
    }

    @VisibleForTesting
    public File[] getAllUploadedFiles() {
        return listCrashFiles(UPLOADED_MINIDUMP_PATTERN);
    }

    @VisibleForTesting
    public File getCrashDirectory() {
        return new File(mCacheDir, CRASH_DUMP_DIR);
    }

    private File getCrashpadDirectory() {
        return new File(mCacheDir, CRASHPAD_DIR);
    }

    public File createNewTempFile(String name) throws IOException {
        File f = new File(getCrashDirectory(), name);
        if (f.exists()) {
            if (f.delete()) {
                f = new File(getCrashDirectory(), name);
            } else {
                Log.w(TAG, "Unable to delete previous logfile" + f.getAbsolutePath());
            }
        }
        return f;
    }

    /**
     * @return the crash file named {@param filename}.
     */
    public File getCrashFile(String filename) {
        return new File(getCrashDirectory(), filename);
    }

    /**
     * Returns the minidump file with the given local ID, or null if no minidump file has the given
     * local ID.
     * NOTE: Crash files that have already been successfully uploaded are not included.
     *
     * @param localId The local ID of the crash report.
     * @return The matching File, or null if no matching file is found.
     */
    public File getCrashFileWithLocalId(String localId) {
        for (File f : listCrashFiles(null)) {
            // Only match non-uploaded or previously skipped files. In particular, do not match
            // successfully uploaded files; nor files which are not minidump files, such as logcat
            // files.
            if (!f.getName().contains(NOT_YET_UPLOADED_MINIDUMP_SUFFIX)
                    && !f.getName().contains(UPLOAD_SKIPPED_MINIDUMP_SUFFIX)
                    && !f.getName().contains(UPLOAD_FORCED_MINIDUMP_SUFFIX)) {
                continue;
            }

            String filenameSansExtension = f.getName().split("\\.")[0];
            if (filenameSansExtension.endsWith(localId)) {
                return f;
            }
        }
        return null;
    }

    /**
     * @return the file used for logging crash upload events.
     */
    public File getCrashUploadLogFile() {
        return new File(getCrashDirectory(), CRASH_DUMP_LOGFILE);
    }

    @VisibleForTesting
    File[] getAllTempFiles() {
        return listCrashFiles(TMP_PATTERN);
    }

    /**
     * Delete the oldest minidump if we have reached our threshold on the number of minidumps to
     * store (either per-app, or globally).
     * @param uid The uid of the app to check the minidump limit for.
     */
    private void enforceMinidumpStorageRestrictions(int uid) {
        File[] allMinidumpFiles = listCrashFiles(MINIDUMP_READY_FOR_UPLOAD_PATTERN);
        List<File> minidumpFilesWithCurrentUid = filterMinidumpFilesOnUid(allMinidumpFiles, uid);

        // If we have exceeded our cap per uid, delete the oldest minidump of the same uid
        if (minidumpFilesWithCurrentUid.size() >= MAX_CRASH_REPORTS_TO_UPLOAD_PER_UID) {
            // Minidumps are sorted from newest to oldest.
            File oldestFile =
                    minidumpFilesWithCurrentUid.get(minidumpFilesWithCurrentUid.size() - 1);
            if (!oldestFile.delete()) {
                // Note that we will still try to copy the new file if this deletion fails.
                Log.w(TAG, "Couldn't delete old minidump " + oldestFile.getAbsolutePath());
            }
            return;
        }

        // If we have exceeded our minidump cap, delete the oldest minidump.
        if (allMinidumpFiles.length >= MAX_CRASH_REPORTS_TO_UPLOAD) {
            // Minidumps are sorted from newest to oldest.
            File oldestFile = allMinidumpFiles[allMinidumpFiles.length - 1];
            if (!oldestFile.delete()) {
                // Note that we will still try to copy the new file if this deletion fails.
                Log.w(TAG, "Couldn't delete old minidump " + oldestFile.getAbsolutePath());
            }
        }
    }

    /**
     * Copy a minidump from the File Descriptor {@param fd}.
     * Use {@param tmpDir} as an intermediate location to store temporary files.
     * @return The new minidump file copied with the contents of the File Descriptor, or null if the
     *         copying failed.
     */
    public File copyMinidumpFromFD(FileDescriptor fd, File tmpDir, int uid) throws IOException {
        File crashDirectory = getCrashDirectory();
        if (!ensureCrashDirExists()) {
            Log.e(TAG, "Crash directory doesn't exist");
            return null;
        }
        // Only threads copying minidumps will be touching this tmp-directory. Since these threads
        // are synchronized to avoid copying several minidumps simultaneously we don't need
        // synchronization explicitly for creating this tmp-directory.
        if (!tmpDir.isDirectory() && !tmpDir.mkdir()) {
            Log.e(TAG, "Couldn't create " + tmpDir.getAbsolutePath());
            return null;
        }
        if (tmpDir.getCanonicalPath().equals(crashDirectory.getCanonicalPath())) {
            // Cause a hard failure since this should never happen in the wild.
            throw new RuntimeException("The tmp-dir and the crash dir can't have the same paths.");
        }

        enforceMinidumpStorageRestrictions(uid);

        // Make sure the temp file doesn't overwrite an existing file.
        File tmpFile = createMinidumpTmpFile(tmpDir);
        FileInputStream in = null;
        FileOutputStream out = null;
        // TODO(gsennton): ensure that the copied file is indeed a minidump.
        try {
            in = new FileInputStream(fd);
            out = new FileOutputStream(tmpFile);
            final int bufSize = 4096;
            byte[] buf = new byte[bufSize];
            final int maxSize = 1024 * 1024; // 1MB maximum size
            int curCount = in.read(buf);
            int totalCount = curCount;
            while ((curCount != -1) && (totalCount < maxSize)) {
                out.write(buf, 0, curCount);
                curCount = in.read(buf);
                totalCount += curCount;
            }
            if (curCount != -1) {
                // We are trying to keep on reading beyond our maximum threshold (1MB) - bail!
                Log.w(TAG, "Tried to copy a file of size > 1MB, deleting the file and bailing!");
                if (!tmpFile.delete()) {
                    Log.w(TAG, "Couldn't delete file " + tmpFile.getAbsolutePath());
                }
                return null;
            }
        } finally {
            try {
                if (out != null) out.close();
            } catch (IOException e) {
                Log.w(TAG, "Couldn't close minidump output stream ", e);
            }
            try {
                if (in != null) in.close();
            } catch (IOException e) {
                Log.w(TAG, "Couldn't close minidump input stream ", e);
            }
        }
        File minidumpFile = new File(crashDirectory, createUniqueMinidumpNameForUid(uid));
        if (tmpFile.renameTo(minidumpFile)) {
            return minidumpFile;
        }
        return null;
    }

    /**
     * Returns whether the {@param minidump} belongs to the uid {@param uid}.
     */
    private static boolean belongsToUid(File minidump, int uid) {
        return minidump.getName().startsWith(uid + UID_DELIMITER);
    }

    /**
     * Returns a unique minidump name based on {@param uid} to differentiate between minidumps from
     * different packages.
     * The 'uniqueness' of the file name lies in it being created from a UUID. A UUID is a
     * Universally Unique ID - it is simply a 128-bit value that can be used to uniquely identify
     * some entity. A uid, on the other hand, is a unique identifier for Android packages.
     */
    private static String createUniqueMinidumpNameForUid(int uid) {
        return uid + UID_DELIMITER + UUID.randomUUID() + NOT_YET_UPLOADED_MINIDUMP_SUFFIX
                + READY_FOR_UPLOAD_SUFFIX;
    }

    /**
     * Create a temporary file to store a minidump in before renaming it with a real minidump name.
     * @return a new temporary file with prefix {@param prefix} stored in the directory
     * {@param directory}.
     *
     */
    private static File createMinidumpTmpFile(File directory) throws IOException {
        return File.createTempFile("webview_minidump", TMP_SUFFIX, directory);
    }
}
