/*
 * 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.server.am;

import android.os.SystemClock;
import android.util.ArrayMap;
import android.util.TimeUtils;

import dalvik.annotation.optimization.NeverCompile;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public final class BroadcastStats {
    final long mStartRealtime;
    final long mStartUptime;
    long mEndRealtime;
    long mEndUptime;
    final ArrayMap<String, ActionEntry> mActions = new ArrayMap<>();

    static final Comparator<ActionEntry> ACTIONS_COMPARATOR = new Comparator<ActionEntry>() {
        @Override public int compare(ActionEntry o1, ActionEntry o2) {
            if (o1.mTotalDispatchTime < o2.mTotalDispatchTime) {
                return -1;
            }
            if (o1.mTotalDispatchTime > o2.mTotalDispatchTime) {
                return 1;
            }
            return 0;
        }
    };

    static final class ActionEntry {
        final String mAction;
        final ArrayMap<String, PackageEntry> mPackages = new ArrayMap<>();
        final ArrayMap<String, ViolationEntry> mBackgroundCheckViolations = new ArrayMap<>();
        int mReceiveCount;
        int mSkipCount;
        long mTotalDispatchTime;
        long mMaxDispatchTime;

        ActionEntry(String action) {
            mAction = action;
        }
    }

    static final class PackageEntry {
        int mSendCount;
    }

    static final class ViolationEntry {
        int mCount;
    }

    public BroadcastStats() {
        mStartRealtime = SystemClock.elapsedRealtime();
        mStartUptime = SystemClock.uptimeMillis();
    }

    public void addBroadcast(String action, String srcPackage, int receiveCount,
            int skipCount, long dispatchTime) {
        ActionEntry ae = mActions.get(action);
        if (ae == null) {
            ae = new ActionEntry(action);
            mActions.put(action, ae);
        }
        ae.mReceiveCount += receiveCount;
        ae.mSkipCount += skipCount;
        ae.mTotalDispatchTime += dispatchTime;
        if (ae.mMaxDispatchTime < dispatchTime) {
            ae.mMaxDispatchTime = dispatchTime;
        }
        PackageEntry pe = ae.mPackages.get(srcPackage);
        if (pe == null) {
            pe = new PackageEntry();
            ae.mPackages.put(srcPackage, pe);
        }
        pe.mSendCount++;
    }

    public void addBackgroundCheckViolation(String action, String targetPackage) {
        ActionEntry ae = mActions.get(action);
        if (ae == null) {
            ae = new ActionEntry(action);
            mActions.put(action, ae);
        }
        ViolationEntry ve = ae.mBackgroundCheckViolations.get(targetPackage);
        if (ve == null) {
            ve = new ViolationEntry();
            ae.mBackgroundCheckViolations.put(targetPackage, ve);
        }
        ve.mCount++;
    }

    @NeverCompile
    public boolean dumpStats(PrintWriter pw, String prefix, String dumpPackage) {
        boolean printedSomething = false;
        ArrayList<ActionEntry> actions = new ArrayList<>(mActions.size());
        for (int i=mActions.size()-1; i>=0; i--) {
            actions.add(mActions.valueAt(i));
        }
        Collections.sort(actions, ACTIONS_COMPARATOR);
        for (int i=actions.size()-1; i>=0; i--) {
            ActionEntry ae = actions.get(i);
            if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
                continue;
            }
            printedSomething = true;
            pw.print(prefix);
            pw.print(ae.mAction);
            pw.println(":");
            pw.print(prefix);
            pw.print("  Number received: ");
            pw.print(ae.mReceiveCount);
            pw.print(", skipped: ");
            pw.println(ae.mSkipCount);
            pw.print(prefix);
            pw.print("  Total dispatch time: ");
            TimeUtils.formatDuration(ae.mTotalDispatchTime, pw);
            pw.print(", max: ");
            TimeUtils.formatDuration(ae.mMaxDispatchTime, pw);
            pw.println();
            for (int j=ae.mPackages.size()-1; j>=0; j--) {
                pw.print(prefix);
                pw.print("  Package ");
                pw.print(ae.mPackages.keyAt(j));
                pw.print(": ");
                PackageEntry pe = ae.mPackages.valueAt(j);
                pw.print(pe.mSendCount);
                pw.println(" times");
            }
            for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
                pw.print(prefix);
                pw.print("  Bg Check Violation ");
                pw.print(ae.mBackgroundCheckViolations.keyAt(j));
                pw.print(": ");
                ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
                pw.print(ve.mCount);
                pw.println(" times");
            }
        }
        return printedSomething;
    }

    @NeverCompile
    public void dumpCheckinStats(PrintWriter pw, String dumpPackage) {
        pw.print("broadcast-stats,1,");
        pw.print(mStartRealtime);
        pw.print(",");
        pw.print(mEndRealtime == 0 ? SystemClock.elapsedRealtime() : mEndRealtime);
        pw.print(",");
        pw.println((mEndUptime == 0 ? SystemClock.uptimeMillis() : mEndUptime) - mStartUptime);
        for (int i=mActions.size()-1; i>=0; i--) {
            ActionEntry ae = mActions.valueAt(i);
            if (dumpPackage != null && !ae.mPackages.containsKey(dumpPackage)) {
                continue;
            }
            pw.print("a,");
            pw.print(mActions.keyAt(i));
            pw.print(",");
            pw.print(ae.mReceiveCount);
            pw.print(",");
            pw.print(ae.mSkipCount);
            pw.print(",");
            pw.print(ae.mTotalDispatchTime);
            pw.print(",");
            pw.print(ae.mMaxDispatchTime);
            pw.println();
            for (int j=ae.mPackages.size()-1; j>=0; j--) {
                pw.print("p,");
                pw.print(ae.mPackages.keyAt(j));
                PackageEntry pe = ae.mPackages.valueAt(j);
                pw.print(",");
                pw.print(pe.mSendCount);
                pw.println();
            }
            for (int j=ae.mBackgroundCheckViolations.size()-1; j>=0; j--) {
                pw.print("v,");
                pw.print(ae.mBackgroundCheckViolations.keyAt(j));
                ViolationEntry ve = ae.mBackgroundCheckViolations.valueAt(j);
                pw.print(",");
                pw.print(ve.mCount);
                pw.println();
            }
        }
    }
}
