// 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.base;

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Process;
import android.os.StrictMode;
import android.os.SystemClock;

import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.MainDex;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Support for early tracing, before the native library is loaded.
 *
 * This is limited, as:
 * - Arguments are not supported
 * - Thread time is not reported
 * - Two events with the same name cannot be in progress at the same time.
 *
 * Events recorded here are buffered in Java until the native library is available. Then it waits
 * for the completion of pending events, and sends the events to the native side.
 *
 * Locking: This class is threadsafe. It is enabled when general tracing is, and then disabled when
 *          tracing is enabled from the native side. Event completions are still processed as long
 *          as some are pending, then early tracing is permanently disabled after dumping the
 *          events.  This means that if any early event is still pending when tracing is disabled,
 *          all early events are dropped.
 */
@JNINamespace("base::android")
@MainDex
public class EarlyTraceEvent {
    // Must be kept in sync with the native kAndroidTraceConfigFile.
    private static final String TRACE_CONFIG_FILENAME = "/data/local/chrome-trace-config.json";

    /** Single trace event. */
    @VisibleForTesting
    static final class Event {
        final String mName;
        final int mThreadId;
        final long mBeginTimeNanos;
        final long mBeginThreadTimeMillis;
        long mEndTimeNanos;
        long mEndThreadTimeMillis;

        Event(String name) {
            mName = name;
            mThreadId = Process.myTid();
            mBeginTimeNanos = elapsedRealtimeNanos();
            mBeginThreadTimeMillis = SystemClock.currentThreadTimeMillis();
        }

        void end() {
            assert mEndTimeNanos == 0;
            assert mEndThreadTimeMillis == 0;
            mEndTimeNanos = elapsedRealtimeNanos();
            mEndThreadTimeMillis = SystemClock.currentThreadTimeMillis();
        }

        @VisibleForTesting
        @SuppressLint("NewApi")
        static long elapsedRealtimeNanos() {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                return SystemClock.elapsedRealtimeNanos();
            } else {
                return SystemClock.elapsedRealtime() * 1000000;
            }
        }
    }

    @VisibleForTesting
    static final class AsyncEvent {
        final boolean mIsStart;
        final String mName;
        final long mId;
        final long mTimestampNanos;

        AsyncEvent(String name, long id, boolean isStart) {
            mName = name;
            mId = id;
            mIsStart = isStart;
            mTimestampNanos = Event.elapsedRealtimeNanos();
        }
    }

    // State transitions are:
    // - enable(): DISABLED -> ENABLED
    // - disable(): ENABLED -> FINISHING
    // - Once there are no pending events: FINISHING -> FINISHED.
    @VisibleForTesting static final int STATE_DISABLED = 0;
    @VisibleForTesting static final int STATE_ENABLED = 1;
    @VisibleForTesting static final int STATE_FINISHING = 2;
    @VisibleForTesting static final int STATE_FINISHED = 3;

    private static final String BACKGROUND_STARTUP_TRACING_ENABLED_KEY = "bg_startup_tracing";
    private static boolean sCachedBackgroundStartupTracingFlag;

    // Locks the fields below.
    private static final Object sLock = new Object();

    @VisibleForTesting static volatile int sState = STATE_DISABLED;
    // Not final as these object are not likely to be used at all.
    @VisibleForTesting static List<Event> sCompletedEvents;
    @VisibleForTesting
    static Map<String, Event> sPendingEventByKey;
    @VisibleForTesting static List<AsyncEvent> sAsyncEvents;
    @VisibleForTesting static List<String> sPendingAsyncEvents;

    /** @see TraceEvent#MaybeEnableEarlyTracing().
     */
    static void maybeEnable() {
        ThreadUtils.assertOnUiThread();
        if (sState != STATE_DISABLED) return;
        boolean shouldEnable = false;
        // Checking for the trace config filename touches the disk.
        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
        try {
            if (CommandLine.getInstance().hasSwitch("trace-startup")) {
                shouldEnable = true;
            } else {
                try {
                    shouldEnable = (new File(TRACE_CONFIG_FILENAME)).exists();
                } catch (SecurityException e) {
                    // Access denied, not enabled.
                }
            }
            if (ContextUtils.getAppSharedPreferences().getBoolean(
                        BACKGROUND_STARTUP_TRACING_ENABLED_KEY, false)) {
                if (shouldEnable) {
                    // If user has enabled tracing, then force disable background tracing for this
                    // session.
                    setBackgroundStartupTracingFlag(false);
                    sCachedBackgroundStartupTracingFlag = false;
                } else {
                    sCachedBackgroundStartupTracingFlag = true;
                    shouldEnable = true;
                }
            }
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
        if (shouldEnable) enable();
    }

    @VisibleForTesting
    static void enable() {
        synchronized (sLock) {
            if (sState != STATE_DISABLED) return;
            sCompletedEvents = new ArrayList<Event>();
            sPendingEventByKey = new HashMap<String, Event>();
            sAsyncEvents = new ArrayList<AsyncEvent>();
            sPendingAsyncEvents = new ArrayList<String>();
            sState = STATE_ENABLED;
        }
    }

    /**
     * Disables Early tracing.
     *
     * Once this is called, no new event will be registered. However, end() calls are still recorded
     * as long as there are pending events. Once there are none left, pass the events to the native
     * side.
     */
    static void disable() {
        synchronized (sLock) {
            if (!enabled()) return;
            sState = STATE_FINISHING;
            maybeFinishLocked();
        }
    }

    /**
     * Returns whether early tracing is currently active.
     *
     * Active means that Early Tracing is either enabled or waiting to complete pending events.
     */
    static boolean isActive() {
        int state = sState;
        return (state == STATE_ENABLED || state == STATE_FINISHING);
    }

    static boolean enabled() {
        return sState == STATE_ENABLED;
    }

    /**
     * Sets the background startup tracing enabled in app preferences for next startup.
     */
    @CalledByNative
    static void setBackgroundStartupTracingFlag(boolean enabled) {
        ContextUtils.getAppSharedPreferences()
                .edit()
                .putBoolean(BACKGROUND_STARTUP_TRACING_ENABLED_KEY, enabled)
                .apply();
    }

    /**
     * Returns true if the background startup tracing flag is set.
     *
     * This does not return the correct value if called before maybeEnable() was called. But that is
     * called really early in startup.
     */
    @CalledByNative
    public static boolean getBackgroundStartupTracingFlag() {
        return sCachedBackgroundStartupTracingFlag;
    }

    /** @see {@link TraceEvent#begin()}. */
    public static void begin(String name) {
        // begin() and end() are going to be called once per TraceEvent, this avoids entering a
        // synchronized block at each and every call.
        if (!enabled()) return;
        Event event = new Event(name);
        Event conflictingEvent;
        synchronized (sLock) {
            if (!enabled()) return;
            conflictingEvent = sPendingEventByKey.put(makeEventKeyForCurrentThread(name), event);
        }
        if (conflictingEvent != null) {
            throw new IllegalArgumentException(
                    "Multiple pending trace events can't have the same name");
        }
    }

    /** @see {@link TraceEvent#end()}. */
    public static void end(String name) {
        if (!isActive()) return;
        synchronized (sLock) {
            if (!isActive()) return;
            Event event = sPendingEventByKey.remove(makeEventKeyForCurrentThread(name));
            if (event == null) return;
            event.end();
            sCompletedEvents.add(event);
            if (sState == STATE_FINISHING) maybeFinishLocked();
        }
    }

    /** @see {@link TraceEvent#startAsync()}. */
    public static void startAsync(String name, long id) {
        if (!enabled()) return;
        AsyncEvent event = new AsyncEvent(name, id, true /*isStart*/);
        synchronized (sLock) {
            if (!enabled()) return;
            sAsyncEvents.add(event);
            sPendingAsyncEvents.add(name);
        }
    }

    /** @see {@link TraceEvent#finishAsync()}. */
    public static void finishAsync(String name, long id) {
        if (!isActive()) return;
        AsyncEvent event = new AsyncEvent(name, id, false /*isStart*/);
        synchronized (sLock) {
            if (!isActive()) return;
            if (!sPendingAsyncEvents.remove(name)) return;
            sAsyncEvents.add(event);
            if (sState == STATE_FINISHING) maybeFinishLocked();
        }
    }

    @VisibleForTesting
    static void resetForTesting() {
        sState = EarlyTraceEvent.STATE_DISABLED;
        sCompletedEvents = null;
        sPendingEventByKey = null;
        sAsyncEvents = null;
        sPendingAsyncEvents = null;
    }

    private static void maybeFinishLocked() {
        if (!sCompletedEvents.isEmpty()) {
            dumpEvents(sCompletedEvents);
            sCompletedEvents.clear();
        }
        if (!sAsyncEvents.isEmpty()) {
            dumpAsyncEvents(sAsyncEvents);
            sAsyncEvents.clear();
        }
        if (sPendingEventByKey.isEmpty() && sPendingAsyncEvents.isEmpty()) {
            sState = STATE_FINISHED;
            sPendingEventByKey = null;
            sCompletedEvents = null;
            sPendingAsyncEvents = null;
            sAsyncEvents = null;
        }
    }

    private static void dumpEvents(List<Event> events) {
        long offsetNanos = getOffsetNanos();
        for (Event e : events) {
            nativeRecordEarlyEvent(e.mName, e.mBeginTimeNanos + offsetNanos,
                    e.mEndTimeNanos + offsetNanos, e.mThreadId,
                    e.mEndThreadTimeMillis - e.mBeginThreadTimeMillis);
        }
    }
    private static void dumpAsyncEvents(List<AsyncEvent> events) {
        long offsetNanos = getOffsetNanos();
        for (AsyncEvent e : events) {
            if (e.mIsStart) {
                nativeRecordEarlyStartAsyncEvent(e.mName, e.mId, e.mTimestampNanos + offsetNanos);
            } else {
                nativeRecordEarlyFinishAsyncEvent(e.mName, e.mId, e.mTimestampNanos + offsetNanos);
            }
        }
    }

    private static long getOffsetNanos() {
        long nativeNowNanos = TimeUtils.nativeGetTimeTicksNowUs() * 1000;
        long javaNowNanos = Event.elapsedRealtimeNanos();
        return nativeNowNanos - javaNowNanos;
    }

    /**
     * Returns a key which consists of |name| and the ID of the current thread.
     * The key is used with pending events making them thread-specific, thus avoiding
     * an exception when similarly named events are started from multiple threads.
     */
    @VisibleForTesting
    static String makeEventKeyForCurrentThread(String name) {
        return name + "@" + Process.myTid();
    }

    private static native void nativeRecordEarlyEvent(String name, long beginTimNanos,
            long endTimeNanos, int threadId, long threadDurationMillis);
    private static native void nativeRecordEarlyStartAsyncEvent(
            String name, long id, long timestamp);
    private static native void nativeRecordEarlyFinishAsyncEvent(
            String name, long id, long timestamp);
}
