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

import static android.os.Environment.STANDARD_DIRECTORIES;
import static com.android.documentsui.DocumentsApplication.acquireUnstableProviderOrThrow;
import static com.android.documentsui.base.Shared.DEBUG;

import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.StringDef;
import android.app.Activity;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Path;
import android.provider.DocumentsProvider;
import android.util.Log;

import com.android.documentsui.base.DocumentInfo;
import com.android.documentsui.base.Providers;
import com.android.documentsui.base.RootInfo;
import com.android.documentsui.base.State;
import com.android.documentsui.base.State.ActionType;
import com.android.documentsui.files.LauncherActivity;
import com.android.documentsui.roots.ProvidersAccess;
import com.android.documentsui.services.FileOperationService;
import com.android.documentsui.services.FileOperationService.OpType;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;

/** @hide */
public final class Metrics {
    private static final String TAG = "Metrics";

    // These strings have to be whitelisted in tron. Do not change them.
    private static final String COUNT_LAUNCH_ACTION = "docsui_launch_action";
    private static final String COUNT_ROOT_VISITED_IN_MANAGER
            = "docsui_root_visited_in_manager";
    private static final String COUNT_ROOT_VISITED_IN_PICKER
            = "docsui_root_visited_in_picker";
    private static final String COUNT_OPEN_MIME = "docsui_open_mime";
    private static final String COUNT_CREATE_MIME = "docsui_create_mime";
    private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
    private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
    @Deprecated private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
    @Deprecated private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
    private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
    private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
    private static final String COUNT_FILEOP_CANCELED = "docsui_fileop_canceled";
    private static final String COUNT_STARTUP_MS = "docsui_startup_ms";
    @Deprecated private static final String COUNT_DRAWER_OPENED = "docsui_drawer_opened";
    private static final String COUNT_USER_ACTION = "docsui_menu_action";
    private static final String COUNT_BROWSE_AT_LOCATION = "docsui_browse_at_location";
    private static final String COUNT_CREATE_AT_LOCATION = "docsui_create_at_location";
    private static final String COUNT_OPEN_AT_LOCATION = "docsui_open_at_location";
    private static final String COUNT_GET_CONTENT_AT_LOCATION = "docsui_get_content_at_location";
    private static final String COUNT_MEDIA_FILEOP_FAILURE = "docsui_media_fileop_failure";
    private static final String COUNT_DOWNLOADS_FILEOP_FAILURE = "docsui_downloads_fileop_failure";
    private static final String COUNT_INTERNAL_STORAGE_FILEOP_FAILURE
            = "docsui_internal_storage_fileop_failure";
    private static final String COUNT_EXTERNAL_STORAGE_FILEOP_FAILURE
            = "docsui_external_storage_fileop_failure";
    private static final String COUNT_MTP_FILEOP_FAILURE = "docsui_mtp_fileop_failure";
    private static final String COUNT_OTHER_FILEOP_FAILURE = "docsui_other_fileop_failure";
    private static final String COUNT_FILE_COPIED = "docsui_file_copied";
    private static final String COUNT_FILE_MOVED = "docsui_file_moved";

    // Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
    // root that is not explicitly recognized by the Metrics code (see {@link
    // #getSanitizedRootIndex}). Apps are also bucketed in this histogram.
    // Do not change or rearrange these values, that will break historical data. Only add to the end
    // of the list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int ROOT_NONE = 1;
    private static final int ROOT_OTHER = 2;
    private static final int ROOT_AUDIO = 3;
    private static final int ROOT_DEVICE_STORAGE = 4;
    private static final int ROOT_DOWNLOADS = 5;
    private static final int ROOT_HOME = 6;
    private static final int ROOT_IMAGES = 7;
    private static final int ROOT_RECENTS = 8;
    private static final int ROOT_VIDEOS = 9;
    private static final int ROOT_MTP = 10;
    // Apps aren't really "roots", but they are treated as such in the roots fragment UI and so they
    // are logged analogously to roots.
    private static final int ROOT_THIRD_PARTY_APP = 100;

    @IntDef(flag = true, value = {
            ROOT_NONE,
            ROOT_OTHER,
            ROOT_AUDIO,
            ROOT_DEVICE_STORAGE,
            ROOT_DOWNLOADS,
            ROOT_HOME,
            ROOT_IMAGES,
            ROOT_RECENTS,
            ROOT_VIDEOS,
            ROOT_MTP,
            ROOT_THIRD_PARTY_APP
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Root {}

    // Indices for bucketing mime types.
    // Do not change or rearrange these values, that will break historical data. Only add to the end
    // of the list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int MIME_NONE = 1; // null mime
    private static final int MIME_ANY = 2; // */*
    private static final int MIME_APPLICATION = 3; // application/*
    private static final int MIME_AUDIO = 4; // audio/*
    private static final int MIME_IMAGE = 5; // image/*
    private static final int MIME_MESSAGE = 6; // message/*
    private static final int MIME_MULTIPART = 7; // multipart/*
    private static final int MIME_TEXT = 8; // text/*
    private static final int MIME_VIDEO = 9; // video/*
    private static final int MIME_OTHER = 10; // anything not enumerated below

    @IntDef(flag = true, value = {
            MIME_NONE,
            MIME_ANY,
            MIME_APPLICATION,
            MIME_AUDIO,
            MIME_IMAGE,
            MIME_MESSAGE,
            MIME_MULTIPART,
            MIME_TEXT,
            MIME_VIDEO,
            MIME_OTHER
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Mime {}

    public static final int FILES_SCOPE = 1;
    public static final int PICKER_SCOPE = 2;

    @IntDef({ FILES_SCOPE, PICKER_SCOPE })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ContextScope {}

    // Codes representing different kinds of file operations. These are used for bucketing
    // operations in the COUNT_FILEOP_{SYSTEM|EXTERNAL} histograms.
    // Do not change or rearrange these values, that will break historical data. Only add to the
    // list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int FILEOP_OTHER = 1; // any file operation not listed below
    private static final int FILEOP_COPY_INTRA_PROVIDER = 2; // Copy within a provider
    private static final int FILEOP_COPY_SYSTEM_PROVIDER = 3; // Copy to a system provider.
    private static final int FILEOP_COPY_EXTERNAL_PROVIDER = 4; // Copy to a 3rd-party provider.
    private static final int FILEOP_MOVE_INTRA_PROVIDER = 5; // Move within a provider.
    private static final int FILEOP_MOVE_SYSTEM_PROVIDER = 6; // Move to a system provider.
    private static final int FILEOP_MOVE_EXTERNAL_PROVIDER = 7; // Move to a 3rd-party provider.
    private static final int FILEOP_DELETE = 8;
    private static final int FILEOP_RENAME = 9;
    private static final int FILEOP_CREATE_DIR = 10;
    private static final int FILEOP_OTHER_ERROR = 100;
    private static final int FILEOP_DELETE_ERROR = 101;
    private static final int FILEOP_MOVE_ERROR = 102;
    private static final int FILEOP_COPY_ERROR = 103;
    private static final int FILEOP_RENAME_ERROR = 104;
    private static final int FILEOP_CREATE_DIR_ERROR = 105;
    private static final int FILEOP_COMPRESS_INTRA_PROVIDER = 106; // Compres within a provider
    private static final int FILEOP_COMPRESS_SYSTEM_PROVIDER = 107; // Compress to a system provider.
    private static final int FILEOP_COMPRESS_EXTERNAL_PROVIDER = 108; // Compress to a 3rd-party provider.
    private static final int FILEOP_EXTRACT_INTRA_PROVIDER = 109; // Extract within a provider
    private static final int FILEOP_EXTRACT_SYSTEM_PROVIDER = 110; // Extract to a system provider.
    private static final int FILEOP_EXTRACT_EXTERNAL_PROVIDER = 111; // Extract to a 3rd-party provider.
    private static final int FILEOP_COMPRESS_ERROR = 112;
    private static final int FILEOP_EXTRACT_ERROR = 113;

    @IntDef(flag = true, value = {
            FILEOP_OTHER,
            FILEOP_COPY_INTRA_PROVIDER,
            FILEOP_COPY_SYSTEM_PROVIDER,
            FILEOP_COPY_EXTERNAL_PROVIDER,
            FILEOP_MOVE_INTRA_PROVIDER,
            FILEOP_MOVE_SYSTEM_PROVIDER,
            FILEOP_MOVE_EXTERNAL_PROVIDER,
            FILEOP_DELETE,
            FILEOP_RENAME,
            FILEOP_CREATE_DIR,
            FILEOP_OTHER_ERROR,
            FILEOP_DELETE_ERROR,
            FILEOP_MOVE_ERROR,
            FILEOP_COPY_ERROR,
            FILEOP_RENAME_ERROR,
            FILEOP_CREATE_DIR_ERROR,
            FILEOP_COMPRESS_INTRA_PROVIDER,
            FILEOP_COMPRESS_SYSTEM_PROVIDER,
            FILEOP_COMPRESS_EXTERNAL_PROVIDER,
            FILEOP_EXTRACT_INTRA_PROVIDER,
            FILEOP_EXTRACT_SYSTEM_PROVIDER,
            FILEOP_EXTRACT_EXTERNAL_PROVIDER,
            FILEOP_COMPRESS_ERROR,
            FILEOP_EXTRACT_ERROR
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface FileOp {}

    // Codes representing different kinds of file operations. These are used for bucketing
    // operations in the COUNT_FILEOP_CANCELED histogram.
    // Do not change or rearrange these values, that will break historical data. Only add to the
    // list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int OPERATION_UNKNOWN = 1;
    private static final int OPERATION_COPY = 2;
    private static final int OPERATION_MOVE = 3;
    private static final int OPERATION_DELETE = 4;
    private static final int OPERATION_COMPRESS = 5;
    private static final int OPERATION_EXTRACT = 6;

    @IntDef(flag = true, value = {
            OPERATION_UNKNOWN,
            OPERATION_COPY,
            OPERATION_MOVE,
            OPERATION_DELETE,
            OPERATION_COMPRESS,
            OPERATION_EXTRACT
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MetricsOpType {}

    // Codes representing different provider types.  Used for sorting file operations when logging.
    private static final int PROVIDER_INTRA = 0;
    private static final int PROVIDER_SYSTEM = 1;
    private static final int PROVIDER_EXTERNAL = 2;

    @IntDef(flag = false, value = {
            PROVIDER_INTRA,
            PROVIDER_SYSTEM,
            PROVIDER_EXTERNAL
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Provider {}

    // Codes representing different types of sub-fileops. These are used for bucketing fileop
    // failures in COUNT_*_FILEOP_FAILURE.
    public static final int SUBFILEOP_QUERY_DOCUMENT = 1;
    public static final int SUBFILEOP_QUERY_CHILDREN = 2;
    public static final int SUBFILEOP_OPEN_FILE = 3;
    public static final int SUBFILEOP_READ_FILE = 4;
    public static final int SUBFILEOP_CREATE_DOCUMENT = 5;
    public static final int SUBFILEOP_WRITE_FILE = 6;
    public static final int SUBFILEOP_DELETE_DOCUMENT = 7;
    public static final int SUBFILEOP_OBTAIN_STREAM_TYPE = 8;
    public static final int SUBFILEOP_QUICK_MOVE = 9;
    public static final int SUBFILEOP_QUICK_COPY = 10;

    @IntDef(flag = false, value = {
            SUBFILEOP_QUERY_DOCUMENT,
            SUBFILEOP_QUERY_CHILDREN,
            SUBFILEOP_OPEN_FILE,
            SUBFILEOP_READ_FILE,
            SUBFILEOP_CREATE_DOCUMENT,
            SUBFILEOP_WRITE_FILE,
            SUBFILEOP_DELETE_DOCUMENT,
            SUBFILEOP_OBTAIN_STREAM_TYPE,
            SUBFILEOP_QUICK_MOVE,
            SUBFILEOP_QUICK_COPY
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface SubFileOp {}

    // Codes representing different user actions. These are used for bucketing stats in the
    // COUNT_USER_ACTION histogram.
    // The historgram includes action triggered from menu or invoked by keyboard shortcut.
    // Do not change or rearrange these values, that will break historical data. Only add to the
    // list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    public static final int USER_ACTION_OTHER = 1;
    public static final int USER_ACTION_GRID = 2;
    public static final int USER_ACTION_LIST = 3;
    public static final int USER_ACTION_SORT_NAME = 4;
    public static final int USER_ACTION_SORT_DATE = 5;
    public static final int USER_ACTION_SORT_SIZE = 6;
    public static final int USER_ACTION_SEARCH = 7;
    public static final int USER_ACTION_SHOW_SIZE = 8;
    public static final int USER_ACTION_HIDE_SIZE = 9;
    public static final int USER_ACTION_SETTINGS = 10;
    public static final int USER_ACTION_COPY_TO = 11;
    public static final int USER_ACTION_MOVE_TO = 12;
    public static final int USER_ACTION_DELETE = 13;
    public static final int USER_ACTION_RENAME = 14;
    public static final int USER_ACTION_CREATE_DIR = 15;
    public static final int USER_ACTION_SELECT_ALL = 16;
    public static final int USER_ACTION_SHARE = 17;
    public static final int USER_ACTION_OPEN = 18;
    public static final int USER_ACTION_SHOW_ADVANCED = 19;
    public static final int USER_ACTION_HIDE_ADVANCED = 20;
    public static final int USER_ACTION_NEW_WINDOW = 21;
    public static final int USER_ACTION_PASTE_CLIPBOARD = 22;
    public static final int USER_ACTION_COPY_CLIPBOARD = 23;
    public static final int USER_ACTION_DRAG_N_DROP = 24;
    public static final int USER_ACTION_DRAG_N_DROP_MULTI_WINDOW = 25;
    public static final int USER_ACTION_CUT_CLIPBOARD = 26;
    public static final int USER_ACTION_COMPRESS = 27;
    public static final int USER_ACTION_EXTRACT_TO = 28;
    public static final int USER_ACTION_VIEW_IN_APPLICATION = 29;

    @IntDef(flag = false, value = {
            USER_ACTION_OTHER,
            USER_ACTION_GRID,
            USER_ACTION_LIST,
            USER_ACTION_SORT_NAME,
            USER_ACTION_SORT_DATE,
            USER_ACTION_SORT_SIZE,
            USER_ACTION_SEARCH,
            USER_ACTION_SHOW_SIZE,
            USER_ACTION_HIDE_SIZE,
            USER_ACTION_SETTINGS,
            USER_ACTION_COPY_TO,
            USER_ACTION_MOVE_TO,
            USER_ACTION_DELETE,
            USER_ACTION_RENAME,
            USER_ACTION_CREATE_DIR,
            USER_ACTION_SELECT_ALL,
            USER_ACTION_SHARE,
            USER_ACTION_OPEN,
            USER_ACTION_SHOW_ADVANCED,
            USER_ACTION_HIDE_ADVANCED,
            USER_ACTION_NEW_WINDOW,
            USER_ACTION_PASTE_CLIPBOARD,
            USER_ACTION_COPY_CLIPBOARD,
            USER_ACTION_DRAG_N_DROP,
            USER_ACTION_DRAG_N_DROP_MULTI_WINDOW,
            USER_ACTION_CUT_CLIPBOARD,
            USER_ACTION_COMPRESS,
            USER_ACTION_EXTRACT_TO,
            USER_ACTION_VIEW_IN_APPLICATION
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface UserAction {}

    // Codes representing different approaches to copy/move a document. OPMODE_PROVIDER indicates
    // it's an optimized operation provided by providers; OPMODE_CONVERTED means it's converted from
    // a virtual file; and OPMODE_CONVENTIONAL means it's byte copied.
    public static final int OPMODE_PROVIDER = 1;
    public static final int OPMODE_CONVERTED = 2;
    public static final int OPMODE_CONVENTIONAL = 3;
    @IntDef({OPMODE_PROVIDER, OPMODE_CONVERTED, OPMODE_CONVENTIONAL})
    @Retention(RetentionPolicy.SOURCE)
    public @interface FileOpMode {}

    // Codes representing different menu actions. These are used for bucketing stats in the
    // COUNT_MENU_ACTION histogram.
    // Do not change or rearrange these values, that will break historical data. Only add to the
    // list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int ACTION_OTHER = 1;
    private static final int ACTION_OPEN = 2;
    private static final int ACTION_CREATE = 3;
    private static final int ACTION_GET_CONTENT = 4;
    private static final int ACTION_OPEN_TREE = 5;
    @Deprecated private static final int ACTION_MANAGE = 6;
    private static final int ACTION_BROWSE = 7;
    private static final int ACTION_PICK_COPY_DESTINATION = 8;

    @IntDef(flag = true, value = {
            ACTION_OTHER,
            ACTION_OPEN,
            ACTION_CREATE,
            ACTION_GET_CONTENT,
            ACTION_OPEN_TREE,
            ACTION_MANAGE,
            ACTION_BROWSE,
            ACTION_PICK_COPY_DESTINATION
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface MetricsAction {}

    // Codes representing different actions to open the drawer. They are used for bucketing stats in
    // the COUNT_DRAWER_OPENED histogram.
    // Do not change or rearrange these values, that will break historical data. Only add to the
    // list.
    // Do not use negative numbers or zero; clearcut only handles positive integers.
    private static final int DRAWER_OPENED_HAMBURGER = 1;
    private static final int DRAWER_OPENED_SWIPE = 2;

    @IntDef(flag = true, value = {
            DRAWER_OPENED_HAMBURGER,
            DRAWER_OPENED_SWIPE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DrawerTrigger {}

    /**
     * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up.
     *
     * @param context
     * @param state
     * @param intent
     */
    public static void logActivityLaunch(Context context, State state, Intent intent) {
        // Log the launch action.
        logHistogram(context, COUNT_LAUNCH_ACTION, toMetricsAction(state.action));
        // Then log auxiliary data (roots/mime types) associated with some actions.
        Uri uri = intent.getData();
        switch (state.action) {
            case State.ACTION_OPEN:
                logHistogram(context, COUNT_OPEN_MIME, sanitizeMime(intent.getType()));
                break;
            case State.ACTION_CREATE:
                logHistogram(context, COUNT_CREATE_MIME, sanitizeMime(intent.getType()));
                break;
            case State.ACTION_GET_CONTENT:
                logHistogram(context, COUNT_GET_CONTENT_MIME, sanitizeMime(intent.getType()));
                break;
            case State.ACTION_BROWSE:
                logHistogram(context, COUNT_BROWSE_ROOT, sanitizeRoot(uri));
                break;
            default:
                break;
        }
    }

    /**
     * Logs when DocumentsUI are launched with {@link DocumentsContract#EXTRA_INITIAL_URI}.
     *
     * @param context
     * @param state used to resolve action
     * @param rootUri the resolved rootUri, or {@code null} if the provider doesn't
     *                support {@link DocumentsProvider#findDocumentPath(String, String)}
     */
    public static void logLaunchAtLocation(Context context, State state, @Nullable Uri rootUri) {
        switch (state.action) {
            case State.ACTION_BROWSE:
                logHistogram(context, COUNT_BROWSE_AT_LOCATION, sanitizeRoot(rootUri));
                break;
            case State.ACTION_CREATE:
                logHistogram(context, COUNT_CREATE_AT_LOCATION, sanitizeRoot(rootUri));
                break;
            case State.ACTION_GET_CONTENT:
                logHistogram(context, COUNT_GET_CONTENT_AT_LOCATION, sanitizeRoot(rootUri));
                break;
            case State.ACTION_OPEN:
                logHistogram(context, COUNT_OPEN_AT_LOCATION, sanitizeRoot(rootUri));
                break;
        }
    }

    /**
     * Logs a root visited event in file managers. Call this when the user
     * taps on a root in {@link com.android.documentsui.sidebar.RootsFragment}.
     *
     * @param context
     * @param scope
     * @param info
     */
    public static void logRootVisited(
            Context context, @ContextScope int scope, RootInfo info) {
        switch (scope) {
            case FILES_SCOPE:
                logHistogram(context, COUNT_ROOT_VISITED_IN_MANAGER,
                        sanitizeRoot(info));
                break;
            case PICKER_SCOPE:
                logHistogram(context, COUNT_ROOT_VISITED_IN_PICKER,
                        sanitizeRoot(info));
                break;
        }
    }

    /**
     * Logs an app visited event in file pickers. Call this when the user visits
     * on an app in the RootsFragment.
     *
     * @param context
     * @param info
     */
    public static void logAppVisited(Context context, ResolveInfo info) {
        logHistogram(context, COUNT_ROOT_VISITED_IN_PICKER, sanitizeRoot(info));
    }

    /**
     * Logs file operation stats. Call this when a file operation has completed. The given
     * DocumentInfo is only used to distinguish broad categories of actions (e.g. copying from one
     * provider to another vs copying within a given provider).  No PII is logged.
     *
     * @param context
     * @param operationType
     * @param srcs
     * @param dst
     */
    public static void logFileOperation(
            Context context,
            @OpType int operationType,
            List<DocumentInfo> srcs,
            @Nullable DocumentInfo dst) {

        ProviderCounts counts = new ProviderCounts();
        countProviders(counts, srcs, dst);

        if (counts.intraProvider > 0) {
            logIntraProviderFileOps(context, dst.authority, operationType);
        }
        if (counts.systemProvider > 0) {
            // Log file operations on system providers.
            logInterProviderFileOps(context, COUNT_FILEOP_SYSTEM, dst, operationType);
        }
        if (counts.externalProvider > 0) {
            // Log file operations on external providers.
            logInterProviderFileOps(context, COUNT_FILEOP_EXTERNAL, dst, operationType);
        }
    }

    public static void logFileOperated(
            Context context, @OpType int operationType, @FileOpMode int approach) {
        switch (operationType) {
            case FileOperationService.OPERATION_COPY:
                logHistogram(context, COUNT_FILE_COPIED, approach);
                break;
            case FileOperationService.OPERATION_MOVE:
                logHistogram(context, COUNT_FILE_MOVED, approach);
                break;
        }
    }

    /**
     * Logs create directory operation. It is a part of file operation stats. We do not
     * differentiate between internal and external locations, all create directory operations are
     * logged under COUNT_FILEOP_SYSTEM. Call this when a create directory operation has completed.
     *
     * @param context
     */
    public static void logCreateDirOperation(Context context) {
        logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR);
    }

    /**
     * Logs rename file operation. It is a part of file operation stats. We do not differentiate
     * between internal and external locations, all rename operations are logged under
     * COUNT_FILEOP_SYSTEM. Call this when a rename file operation has completed.
     *
     * @param context
     */
    public static void logRenameFileOperation(Context context) {
        logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_RENAME);
    }

    /**
     * Logs some kind of file operation error. Call this when a file operation (e.g. copy, delete)
     * fails.
     *
     * @param context
     * @param operationType
     * @param failedFiles
     */
    public static void logFileOperationErrors(Context context, @OpType int operationType,
            List<DocumentInfo> failedFiles, List<Uri> failedUris) {

        ProviderCounts counts = new ProviderCounts();
        countProviders(counts, failedFiles, null);

        // TODO: Report URI errors separate from file operation errors.
        countProviders(counts, failedUris);

        @FileOp int opCode = FILEOP_OTHER_ERROR;
        switch (operationType) {
            case FileOperationService.OPERATION_COPY:
                opCode = FILEOP_COPY_ERROR;
                break;
            case FileOperationService.OPERATION_COMPRESS:
                opCode = FILEOP_COMPRESS_ERROR;
                break;
            case FileOperationService.OPERATION_EXTRACT:
                opCode = FILEOP_EXTRACT_ERROR;
                break;
            case FileOperationService.OPERATION_DELETE:
                opCode = FILEOP_DELETE_ERROR;
                break;
            case FileOperationService.OPERATION_MOVE:
                opCode = FILEOP_MOVE_ERROR;
                break;
        }
        if (counts.systemProvider > 0) {
            logHistogram(context, COUNT_FILEOP_SYSTEM, opCode);
        }
        if (counts.externalProvider > 0) {
            logHistogram(context, COUNT_FILEOP_EXTERNAL, opCode);
        }
    }

    public static void logFileOperationFailure(
            Context context, @SubFileOp int subFileOp, Uri docUri) {
        final String authority = docUri.getAuthority();
        switch (authority) {
            case Providers.AUTHORITY_MEDIA:
                logHistogram(context, COUNT_MEDIA_FILEOP_FAILURE, subFileOp);
                break;
            case Providers.AUTHORITY_STORAGE:
                logStorageFileOperationFailure(context, subFileOp, docUri);
                break;
            case Providers.AUTHORITY_DOWNLOADS:
                logHistogram(context, COUNT_DOWNLOADS_FILEOP_FAILURE, subFileOp);
                break;
            case Providers.AUTHORITY_MTP:
                logHistogram(context, COUNT_MTP_FILEOP_FAILURE, subFileOp);
                break;
            default:
                logHistogram(context, COUNT_OTHER_FILEOP_FAILURE, subFileOp);
                break;
        }
    }

    /**
     * Logs create directory operation error. We do not differentiate between internal and external
     * locations, all create directory errors are logged under COUNT_FILEOP_SYSTEM. Call this when a
     * create directory operation fails.
     *
     * @param context
     */
    public static void logCreateDirError(Context context) {
        logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR_ERROR);
    }

    /**
     * Logs rename file operation error. We do not differentiate between internal and external
     * locations, all rename errors are logged under COUNT_FILEOP_SYSTEM. Call this
     * when a rename file operation fails.
     *
     * @param context
     */
    public static void logRenameFileError(Context context) {
        logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_RENAME_ERROR);
    }

    /**
     * Logs the cancellation of a file operation.  Call this when a Job is canceled.
     * @param context
     * @param operationType
     */
    public static void logFileOperationCancelled(Context context, @OpType int operationType) {
        logHistogram(context, COUNT_FILEOP_CANCELED, toMetricsOpType(operationType));
    }

    /**
     * Logs startup time in milliseconds.
     * @param context
     * @param startupMs Startup time in milliseconds.
     */
    public static void logStartupMs(Context context, int startupMs) {
        logHistogram(context, COUNT_STARTUP_MS, startupMs);
    }

    private static void logInterProviderFileOps(
            Context context,
            String histogram,
            DocumentInfo dst,
            @OpType int operationType) {
        if (operationType == FileOperationService.OPERATION_DELETE) {
            logHistogram(context, histogram, FILEOP_DELETE);
        } else {
            assert(dst != null);
            @Provider int providerType =
                    isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
            logHistogram(context, histogram, getOpCode(operationType, providerType));
        }
    }

    private static void logIntraProviderFileOps(
            Context context, String authority, @OpType int operationType) {
        // Find the right histogram to log to, then log the operation.
        String histogram = isSystemProvider(authority) ? COUNT_FILEOP_SYSTEM : COUNT_FILEOP_EXTERNAL;
        logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
    }

    // Types for logInvalidScopedAccessRequest
    public static final String SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS =
            "docsui_scoped_directory_access_invalid_args";
    public static final String SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY =
            "docsui_scoped_directory_access_invalid_dir";
    public static final String SCOPED_DIRECTORY_ACCESS_ERROR =
            "docsui_scoped_directory_access_error";

    @StringDef(value = {
            SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS,
            SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY,
            SCOPED_DIRECTORY_ACCESS_ERROR
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface InvalidScopedAccess{}

    public static void logInvalidScopedAccessRequest(Context context,
            @InvalidScopedAccess String type) {
        switch (type) {
            case SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS:
            case SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY:
            case SCOPED_DIRECTORY_ACCESS_ERROR:
                logCount(context, type);
                break;
            default:
                Log.wtf(TAG, "invalid InvalidScopedAccess: " + type);
        }
    }

    // Types for logValidScopedAccessRequest
    public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED = 0;
    public static final int SCOPED_DIRECTORY_ACCESS_GRANTED = 1;
    public static final int SCOPED_DIRECTORY_ACCESS_DENIED = 2;
    public static final int SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST = 3;
    public static final int SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED = 4;

    @IntDef(flag = true, value = {
            SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED,
            SCOPED_DIRECTORY_ACCESS_GRANTED,
            SCOPED_DIRECTORY_ACCESS_DENIED,
            SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST,
            SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface ScopedAccessGrant {}

    public static void logValidScopedAccessRequest(Activity activity, String directory,
            @ScopedAccessGrant int type) {
        int index = -1;
        if (OpenExternalDirectoryActivity.DIRECTORY_ROOT.equals(directory)) {
            index = -2;
        } else {
            for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
                if (STANDARD_DIRECTORIES[i].equals(directory)) {
                    index = i;
                    break;
                }
            }
        }
        final String packageName = activity.getCallingPackage();
        switch (type) {
            case SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED:
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_PACKAGE, packageName);
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER, index);
                break;
            case SCOPED_DIRECTORY_ACCESS_GRANTED:
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_PACKAGE, packageName);
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER, index);
                break;
            case SCOPED_DIRECTORY_ACCESS_DENIED:
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_PACKAGE, packageName);
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER, index);
                break;
            case SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST:
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE, packageName);
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER, index);
                break;
            case SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED:
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_PACKAGE, packageName);
                MetricsLogger.action(activity, MetricsEvent
                        .ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER, index);
                break;
            default:
                Log.wtf(TAG, "invalid ScopedAccessGrant: " + type);
        }
    }

    /**
     * Logs the action that was started by user.
     * @param context
     * @param userAction
     */
    public static void logUserAction(Context context, @UserAction int userAction) {
        logHistogram(context, COUNT_USER_ACTION, userAction);
    }

    private static void logStorageFileOperationFailure(
            Context context, @SubFileOp int subFileOp, Uri docUri) {
        assert(Providers.AUTHORITY_STORAGE.equals(docUri.getAuthority()));

        boolean isInternal;
        try (ContentProviderClient client = acquireUnstableProviderOrThrow(
                context.getContentResolver(), Providers.AUTHORITY_STORAGE)) {
            final Path path = DocumentsContract.findDocumentPath(client, docUri);

            final ProvidersAccess providers = DocumentsApplication.getProvidersCache(context);
            final RootInfo root = providers.getRootOneshot(
                    Providers.AUTHORITY_STORAGE, path.getRootId());
            isInternal = !root.supportsEject();
        } catch (RemoteException | RuntimeException e) {
            Log.e(TAG, "Failed to obtain its root info. Log the metrics as internal.", e);
            // It's not very likely to have an external storage so log it as internal.
            isInternal = true;
        }

        final String histogram = isInternal
                ? COUNT_INTERNAL_STORAGE_FILEOP_FAILURE
                : COUNT_EXTERNAL_STORAGE_FILEOP_FAILURE;
        logHistogram(context, histogram, subFileOp);
    }

    /**
     * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
     *
     * @param context
     * @param name The counter to increment.
     */
    private static void logCount(Context context, String name) {
        if (DEBUG) Log.d(TAG, name + ": " + 1);
        MetricsLogger.count(context, name, 1);
    }

    /**
     * Internal method for making a MetricsLogger.histogram call.
     *
     * @param context
     * @param name The name of the histogram.
     * @param bucket The bucket to increment.
     */
    private static void logHistogram(Context context, String name, @ActionType int bucket) {
        if (DEBUG) Log.d(TAG, name + ": " + bucket);
        MetricsLogger.histogram(context, name, bucket);
    }

    /**
     * Generates an integer identifying the given root. For privacy, this function only recognizes a
     * small set of hard-coded roots (ones provided by the system). Other roots are all grouped into
     * a single ROOT_OTHER bucket.
     */
    private static @Root int sanitizeRoot(Uri uri) {
        if (uri == null || uri.getAuthority() == null || LauncherActivity.isLaunchUri(uri)) {
            return ROOT_NONE;
        }

        switch (uri.getAuthority()) {
            case Providers.AUTHORITY_MEDIA:
                switch (DocumentsContract.getRootId(uri)) {
                    case Providers.ROOT_ID_AUDIO:
                        return ROOT_AUDIO;
                    case Providers.ROOT_ID_IMAGES:
                        return ROOT_IMAGES;
                    case Providers.ROOT_ID_VIDEOS:
                        return ROOT_VIDEOS;
                    default:
                        return ROOT_OTHER;
                }
            case Providers.AUTHORITY_STORAGE:
                if (Providers.ROOT_ID_HOME.equals(DocumentsContract.getRootId(uri))) {
                    return ROOT_HOME;
                } else {
                    return ROOT_DEVICE_STORAGE;
                }
            case Providers.AUTHORITY_DOWNLOADS:
                return ROOT_DOWNLOADS;
            case Providers.AUTHORITY_MTP:
                return ROOT_MTP;
            default:
                return ROOT_OTHER;
        }
    }

    /** @see #sanitizeRoot(Uri) */
    private static @Root int sanitizeRoot(RootInfo root) {
        if (root.isRecents()) {
            // Recents root is special and only identifiable via this method call. Other roots are
            // identified by URI.
            return ROOT_RECENTS;
        } else {
            return sanitizeRoot(root.getUri());
        }
    }

    /** @see #sanitizeRoot(Uri) */
    private static @Root int sanitizeRoot(ResolveInfo info) {
        // Log all apps under a single bucket in the roots histogram.
        return ROOT_THIRD_PARTY_APP;
    }

    /**
     * Generates an int identifying a mime type. For privacy, this function only recognizes a small
     * set of hard-coded types. For any other type, this function returns "other".
     *
     * @param mimeType
     * @return
     */
    private static @Mime int sanitizeMime(String mimeType) {
        if (mimeType == null) {
            return MIME_NONE;
        } else if ("*/*".equals(mimeType)) {
            return MIME_ANY;
        } else {
            String type = mimeType.substring(0, mimeType.indexOf('/'));
            switch (type) {
                case "application":
                    return MIME_APPLICATION;
                case "audio":
                    return MIME_AUDIO;
                case "image":
                    return MIME_IMAGE;
                case "message":
                    return MIME_MESSAGE;
                case "multipart":
                    return MIME_MULTIPART;
                case "text":
                    return MIME_TEXT;
                case "video":
                    return MIME_VIDEO;
            }
        }
        // Bucket all other types into one bucket.
        return MIME_OTHER;
    }

    private static boolean isSystemProvider(String authority) {
        switch (authority) {
            case Providers.AUTHORITY_MEDIA:
            case Providers.AUTHORITY_STORAGE:
            case Providers.AUTHORITY_DOWNLOADS:
                return true;
            default:
                return false;
        }
    }

    /**
     * @param operation
     * @param providerType
     * @return An opcode, suitable for use as histogram bucket, for the given operation/provider
     *         combination.
     */
    private static @FileOp int getOpCode(@OpType int operation, @Provider int providerType) {
        switch (operation) {
            case FileOperationService.OPERATION_COPY:
                switch (providerType) {
                    case PROVIDER_INTRA:
                        return FILEOP_COPY_INTRA_PROVIDER;
                    case PROVIDER_SYSTEM:
                        return FILEOP_COPY_SYSTEM_PROVIDER;
                    case PROVIDER_EXTERNAL:
                        return FILEOP_COPY_EXTERNAL_PROVIDER;
                }
            case FileOperationService.OPERATION_COMPRESS:
                switch (providerType) {
                    case PROVIDER_INTRA:
                        return FILEOP_COMPRESS_INTRA_PROVIDER;
                    case PROVIDER_SYSTEM:
                        return FILEOP_COMPRESS_SYSTEM_PROVIDER;
                    case PROVIDER_EXTERNAL:
                        return FILEOP_COMPRESS_EXTERNAL_PROVIDER;
                }
             case FileOperationService.OPERATION_EXTRACT:
                switch (providerType) {
                    case PROVIDER_INTRA:
                        return FILEOP_EXTRACT_INTRA_PROVIDER;
                    case PROVIDER_SYSTEM:
                        return FILEOP_EXTRACT_SYSTEM_PROVIDER;
                    case PROVIDER_EXTERNAL:
                        return FILEOP_EXTRACT_EXTERNAL_PROVIDER;
                }
            case FileOperationService.OPERATION_MOVE:
                switch (providerType) {
                    case PROVIDER_INTRA:
                        return FILEOP_MOVE_INTRA_PROVIDER;
                    case PROVIDER_SYSTEM:
                        return FILEOP_MOVE_SYSTEM_PROVIDER;
                    case PROVIDER_EXTERNAL:
                        return FILEOP_MOVE_EXTERNAL_PROVIDER;
                }
            case FileOperationService.OPERATION_DELETE:
                return FILEOP_DELETE;
            default:
                Log.w(TAG, "Unrecognized operation type when logging a file operation");
                return FILEOP_OTHER;
        }
    }

    /**
     * Maps FileOperationService OpType values, to MetricsOpType values.
     */
    private static @MetricsOpType int toMetricsOpType(@OpType int operation) {
        switch (operation) {
            case FileOperationService.OPERATION_COPY:
                return OPERATION_COPY;
            case FileOperationService.OPERATION_MOVE:
                return OPERATION_MOVE;
            case FileOperationService.OPERATION_DELETE:
                return OPERATION_DELETE;
            case FileOperationService.OPERATION_UNKNOWN:
            default:
                return OPERATION_UNKNOWN;
        }
    }

    private static @MetricsAction int toMetricsAction(int action) {
        switch(action) {
            case State.ACTION_OPEN:
                return ACTION_OPEN;
            case State.ACTION_CREATE:
                return ACTION_CREATE;
            case State.ACTION_GET_CONTENT:
                return ACTION_GET_CONTENT;
            case State.ACTION_OPEN_TREE:
                return ACTION_OPEN_TREE;
            case State.ACTION_BROWSE:
                return ACTION_BROWSE;
            case State.ACTION_PICK_COPY_DESTINATION:
                return ACTION_PICK_COPY_DESTINATION;
            default:
                return ACTION_OTHER;
        }
    }

    /**
     * Count the given src documents and provide a tally of how many come from the same provider as
     * the dst document (if a dst is provided), how many come from system providers, and how many
     * come from external 3rd-party providers.
     */
    private static void countProviders(
            ProviderCounts counts, List<DocumentInfo> srcs, @Nullable DocumentInfo dst) {
        for (DocumentInfo doc: srcs) {
            countForAuthority(counts, doc.authority, dst);
        }
    }

    /**
     * Count the given uris and provide a tally of how many come from the same provider as
     * the dst document (if a dst is provided), how many come from system providers, and how many
     * come from external 3rd-party providers.
     */
    private static void countProviders(ProviderCounts counts, List<Uri> uris) {
        for (Uri uri: uris) {
            countForAuthority(counts, uri.getAuthority(), null);
        }
    }

    private static void countForAuthority(
            ProviderCounts counts, String authority, @Nullable DocumentInfo dst) {
        if (dst != null && authority.equals(dst.authority)) {
            counts.intraProvider++;
        } else if (isSystemProvider(authority)){
            counts.systemProvider++;
        } else {
            counts.externalProvider++;
        }
    }

    private static class ProviderCounts {
        int intraProvider;
        int systemProvider;
        int externalProvider;
    }
}
