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

package com.android.systemui.util.leak;

import static android.service.quicksettings.Tile.STATE_ACTIVE;
import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE;

import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.LongSparseArray;

import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 */
@Singleton
public class GarbageMonitor implements Dumpable {
    private static final boolean LEAK_REPORTING_ENABLED =
            Build.IS_DEBUGGABLE
                    && SystemProperties.getBoolean("debug.enable_leak_reporting", false);
    private static final String FORCE_ENABLE_LEAK_REPORTING = "sysui_force_enable_leak_reporting";

    private static final boolean HEAP_TRACKING_ENABLED = Build.IS_DEBUGGABLE;

    // whether to use ActivityManager.setHeapLimit
    private static final boolean ENABLE_AM_HEAP_LIMIT = Build.IS_DEBUGGABLE;
    // heap limit value, in KB (overrides R.integer.watch_heap_limit)
    private static final String SETTINGS_KEY_AM_HEAP_LIMIT = "systemui_am_heap_limit";

    private static final String TAG = "GarbageMonitor";

    private static final long GARBAGE_INSPECTION_INTERVAL =
            15 * DateUtils.MINUTE_IN_MILLIS; // 15 min
    private static final long HEAP_TRACK_INTERVAL = 1 * DateUtils.MINUTE_IN_MILLIS; // 1 min
    private static final int HEAP_TRACK_HISTORY_LEN = 720; // 12 hours

    private static final int DO_GARBAGE_INSPECTION = 1000;
    private static final int DO_HEAP_TRACK = 3000;

    private static final int GARBAGE_ALLOWANCE = 5;

    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private final Handler mHandler;
    private final TrackedGarbage mTrackedGarbage;
    private final LeakReporter mLeakReporter;
    private final Context mContext;
    private final ActivityManager mAm;
    private MemoryTile mQSTile;
    private DumpTruck mDumpTruck;

    private final LongSparseArray<ProcessMemInfo> mData = new LongSparseArray<>();
    private final ArrayList<Long> mPids = new ArrayList<>();

    private long mHeapLimit;

    /**
     */
    @Inject
    public GarbageMonitor(
            Context context,
            @BgLooper Looper bgLooper,
            LeakDetector leakDetector,
            LeakReporter leakReporter) {
        mContext = context.getApplicationContext();
        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

        mHandler = new BackgroundHeapCheckHandler(bgLooper);

        mTrackedGarbage = leakDetector.getTrackedGarbage();
        mLeakReporter = leakReporter;

        mDumpTruck = new DumpTruck(mContext);

        if (ENABLE_AM_HEAP_LIMIT) {
            mHeapLimit = Settings.Global.getInt(context.getContentResolver(),
                    SETTINGS_KEY_AM_HEAP_LIMIT,
                    mContext.getResources().getInteger(R.integer.watch_heap_limit));
        }
    }

    public void startLeakMonitor() {
        if (mTrackedGarbage == null) {
            return;
        }

        mHandler.sendEmptyMessage(DO_GARBAGE_INSPECTION);
    }

    public void startHeapTracking() {
        startTrackingProcess(
                android.os.Process.myPid(), mContext.getPackageName(), System.currentTimeMillis());
        mHandler.sendEmptyMessage(DO_HEAP_TRACK);
    }

    private boolean gcAndCheckGarbage() {
        if (mTrackedGarbage.countOldGarbage() > GARBAGE_ALLOWANCE) {
            Runtime.getRuntime().gc();
            return true;
        }
        return false;
    }

    void reinspectGarbageAfterGc() {
        int count = mTrackedGarbage.countOldGarbage();
        if (count > GARBAGE_ALLOWANCE) {
            mLeakReporter.dumpLeak(count);
        }
    }

    public ProcessMemInfo getMemInfo(int pid) {
        return mData.get(pid);
    }

    public List<Long> getTrackedProcesses() {
        return mPids;
    }

    public void startTrackingProcess(long pid, String name, long start) {
        synchronized (mPids) {
            if (mPids.contains(pid)) return;

            mPids.add(pid);
            logPids();

            mData.put(pid, new ProcessMemInfo(pid, name, start));
        }
    }

    private void logPids() {
        if (DEBUG) {
            StringBuffer sb = new StringBuffer("Now tracking processes: ");
            for (int i = 0; i < mPids.size(); i++) {
                final int p = mPids.get(i).intValue();
                sb.append(" ");
            }
            Log.v(TAG, sb.toString());
        }
    }

    private void update() {
        synchronized (mPids) {
            for (int i = 0; i < mPids.size(); i++) {
                final int pid = mPids.get(i).intValue();
                // rssValues contains [VmRSS, RssFile, RssAnon, VmSwap].
                long[] rssValues = Process.getRss(pid);
                if (rssValues == null && rssValues.length == 0) {
                    if (DEBUG) Log.e(TAG, "update: Process.getRss() didn't provide any values.");
                    break;
                }
                long rss = rssValues[0];
                final ProcessMemInfo info = mData.get(pid);
                info.rss[info.head] = info.currentRss = rss;
                info.head = (info.head + 1) % info.rss.length;
                if (info.currentRss > info.max) info.max = info.currentRss;
                if (info.currentRss == 0) {
                    if (DEBUG) Log.v(TAG, "update: pid " + pid + " has rss=0, it probably died");
                    mData.remove(pid);
                }
            }
            for (int i = mPids.size() - 1; i >= 0; i--) {
                final long pid = mPids.get(i).intValue();
                if (mData.get(pid) == null) {
                    mPids.remove(i);
                    logPids();
                }
            }
        }
        if (mQSTile != null) mQSTile.update();
    }

    private void setTile(MemoryTile tile) {
        mQSTile = tile;
        if (tile != null) tile.update();
    }

    private static String formatBytes(long b) {
        String[] SUFFIXES = {"B", "K", "M", "G", "T"};
        int i;
        for (i = 0; i < SUFFIXES.length; i++) {
            if (b < 1024) break;
            b /= 1024;
        }
        return b + SUFFIXES[i];
    }

    private Intent dumpHprofAndGetShareIntent() {
        return mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent();
    }

    @Override
    public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
        pw.println("GarbageMonitor params:");
        pw.println(String.format("   mHeapLimit=%d KB", mHeapLimit));
        pw.println(String.format("   GARBAGE_INSPECTION_INTERVAL=%d (%.1f mins)",
                GARBAGE_INSPECTION_INTERVAL,
                (float) GARBAGE_INSPECTION_INTERVAL / DateUtils.MINUTE_IN_MILLIS));
        final float htiMins = HEAP_TRACK_INTERVAL / DateUtils.MINUTE_IN_MILLIS;
        pw.println(String.format("   HEAP_TRACK_INTERVAL=%d (%.1f mins)",
                HEAP_TRACK_INTERVAL,
                htiMins));
        pw.println(String.format("   HEAP_TRACK_HISTORY_LEN=%d (%.1f hr total)",
                HEAP_TRACK_HISTORY_LEN,
                (float) HEAP_TRACK_HISTORY_LEN * htiMins / 60f));

        pw.println("GarbageMonitor tracked processes:");

        for (long pid : mPids) {
            final ProcessMemInfo pmi = mData.get(pid);
            if (pmi != null) {
                pmi.dump(fd, pw, args);
            }
        }
    }


    private static class MemoryIconDrawable extends Drawable {
        long rss, limit;
        final Drawable baseIcon;
        final Paint paint = new Paint();
        final float dp;

        MemoryIconDrawable(Context context) {
            baseIcon = context.getDrawable(R.drawable.ic_memory).mutate();
            dp = context.getResources().getDisplayMetrics().density;
            paint.setColor(QSTileImpl.getColorForState(context, STATE_ACTIVE));
        }

        public void setRss(long rss) {
            if (rss != this.rss) {
                this.rss = rss;
                invalidateSelf();
            }
        }

        public void setLimit(long limit) {
            if (limit != this.limit) {
                this.limit = limit;
                invalidateSelf();
            }
        }

        @Override
        public void draw(Canvas canvas) {
            baseIcon.draw(canvas);

            if (limit > 0 && rss > 0) {
                float frac = Math.min(1f, (float) rss / limit);

                final Rect bounds = getBounds();
                canvas.translate(bounds.left + 8 * dp, bounds.top + 5 * dp);
                //android:pathData="M16.0,5.0l-8.0,0.0l0.0,14.0l8.0,0.0z"
                canvas.drawRect(0, 14 * dp * (1 - frac), 8 * dp + 1, 14 * dp + 1, paint);
            }
        }

        @Override
        public void setBounds(int left, int top, int right, int bottom) {
            super.setBounds(left, top, right, bottom);
            baseIcon.setBounds(left, top, right, bottom);
        }

        @Override
        public int getIntrinsicHeight() {
            return baseIcon.getIntrinsicHeight();
        }

        @Override
        public int getIntrinsicWidth() {
            return baseIcon.getIntrinsicWidth();
        }

        @Override
        public void setAlpha(int i) {
            baseIcon.setAlpha(i);
        }

        @Override
        public void setColorFilter(ColorFilter colorFilter) {
            baseIcon.setColorFilter(colorFilter);
            paint.setColorFilter(colorFilter);
        }

        @Override
        public void setTint(int tint) {
            super.setTint(tint);
            baseIcon.setTint(tint);
        }

        @Override
        public void setTintList(ColorStateList tint) {
            super.setTintList(tint);
            baseIcon.setTintList(tint);
        }

        @Override
        public void setTintMode(PorterDuff.Mode tintMode) {
            super.setTintMode(tintMode);
            baseIcon.setTintMode(tintMode);
        }

        @Override
        public int getOpacity() {
            return PixelFormat.TRANSLUCENT;
        }
    }

    private static class MemoryGraphIcon extends QSTile.Icon {
        long rss, limit;

        public void setRss(long rss) {
            this.rss = rss;
        }

        public void setHeapLimit(long limit) {
            this.limit = limit;
        }

        @Override
        public Drawable getDrawable(Context context) {
            final MemoryIconDrawable drawable = new MemoryIconDrawable(context);
            drawable.setRss(rss);
            drawable.setLimit(limit);
            return drawable;
        }
    }

    public static class MemoryTile extends QSTileImpl<QSTile.State> {
        public static final String TILE_SPEC = "dbg:mem";

        // Tell QSTileHost.java to toss this into the default tileset?
        public static final boolean ADD_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;

        private final GarbageMonitor gm;
        private final ActivityStarter mActivityStarter;
        private ProcessMemInfo pmi;
        private boolean dumpInProgress;

        @Inject
        public MemoryTile(QSHost host, GarbageMonitor monitor, ActivityStarter starter) {
            super(host);
            gm = monitor;
            mActivityStarter = starter;
        }

        @Override
        public State newTileState() {
            return new QSTile.State();
        }

        @Override
        public Intent getLongClickIntent() {
            return new Intent();
        }

        @Override
        protected void handleClick() {
            if (dumpInProgress) return;

            dumpInProgress = true;
            refreshState();
            new Thread("HeapDumpThread") {
                @Override
                public void run() {
                    try {
                        // wait for animations & state changes
                        Thread.sleep(500);
                    } catch (InterruptedException ignored) { }
                    final Intent shareIntent = gm.dumpHprofAndGetShareIntent();
                    mHandler.post(() -> {
                        dumpInProgress = false;
                        refreshState();
                        getHost().collapsePanels();
                        mActivityStarter.postStartActivityDismissingKeyguard(shareIntent, 0);
                    });
                }
            }.start();
        }

        @Override
        public int getMetricsCategory() {
            return VIEW_UNKNOWN;
        }

        @Override
        public void handleSetListening(boolean listening) {
            if (gm != null) gm.setTile(listening ? this : null);

            final ActivityManager am = mContext.getSystemService(ActivityManager.class);
            if (listening && gm.mHeapLimit > 0) {
                am.setWatchHeapLimit(1024 * gm.mHeapLimit); // why is this in bytes?
            } else {
                am.clearWatchHeapLimit();
            }
        }

        @Override
        public CharSequence getTileLabel() {
            return getState().label;
        }

        @Override
        protected void handleUpdateState(State state, Object arg) {
            pmi = gm.getMemInfo(Process.myPid());
            final MemoryGraphIcon icon = new MemoryGraphIcon();
            icon.setHeapLimit(gm.mHeapLimit);
            state.state = dumpInProgress ? STATE_UNAVAILABLE : STATE_ACTIVE;
            state.label = dumpInProgress
                    ? "Dumping..."
                    : mContext.getString(R.string.heap_dump_tile_name);
            if (pmi != null) {
                icon.setRss(pmi.currentRss);
                state.secondaryLabel =
                        String.format(
                                "rss: %s / %s",
                                formatBytes(pmi.currentRss * 1024),
                                formatBytes(gm.mHeapLimit * 1024));
            } else {
                icon.setRss(0);
                state.secondaryLabel = null;
            }
            state.icon = icon;
        }

        public void update() {
            refreshState();
        }

        public long getRss() {
            return pmi != null ? pmi.currentRss : 0;
        }

        public long getHeapLimit() {
            return gm != null ? gm.mHeapLimit : 0;
        }
    }

    /** */
    public static class ProcessMemInfo implements Dumpable {
        public long pid;
        public String name;
        public long startTime;
        public long currentRss;
        public long[] rss = new long[HEAP_TRACK_HISTORY_LEN];
        public long max = 1;
        public int head = 0;

        public ProcessMemInfo(long pid, String name, long start) {
            this.pid = pid;
            this.name = name;
            this.startTime = start;
        }

        public long getUptime() {
            return System.currentTimeMillis() - startTime;
        }

        @Override
        public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
            pw.print("{ \"pid\": ");
            pw.print(pid);
            pw.print(", \"name\": \"");
            pw.print(name.replace('"', '-'));
            pw.print("\", \"start\": ");
            pw.print(startTime);
            pw.print(", \"rss\": [");
            // write rss values starting from the oldest, which is rss[head], wrapping around to
            // rss[(head-1) % rss.length]
            for (int i = 0; i < rss.length; i++) {
                if (i > 0) pw.print(",");
                pw.print(rss[(head + i) % rss.length]);
            }
            pw.println("] }");
        }
    }

    /** */
    @Singleton
    public static class Service extends SystemUI implements Dumpable {
        private final GarbageMonitor mGarbageMonitor;

        @Inject
        public Service(Context context, GarbageMonitor garbageMonitor) {
            super(context);
            mGarbageMonitor = garbageMonitor;
        }

        @Override
        public void start() {
            boolean forceEnable =
                    Settings.Secure.getInt(
                                    mContext.getContentResolver(), FORCE_ENABLE_LEAK_REPORTING, 0)
                            != 0;
            if (LEAK_REPORTING_ENABLED || forceEnable) {
                mGarbageMonitor.startLeakMonitor();
            }
            if (HEAP_TRACKING_ENABLED || forceEnable) {
                mGarbageMonitor.startHeapTracking();
            }
        }

        @Override
        public void dump(@Nullable FileDescriptor fd, PrintWriter pw, @Nullable String[] args) {
            if (mGarbageMonitor != null) mGarbageMonitor.dump(fd, pw, args);
        }
    }

    private class BackgroundHeapCheckHandler extends Handler {
        BackgroundHeapCheckHandler(Looper onLooper) {
            super(onLooper);
            if (Looper.getMainLooper().equals(onLooper)) {
                throw new RuntimeException(
                        "BackgroundHeapCheckHandler may not run on the ui thread");
            }
        }

        @Override
        public void handleMessage(Message m) {
            switch (m.what) {
                case DO_GARBAGE_INSPECTION:
                    if (gcAndCheckGarbage()) {
                        postDelayed(GarbageMonitor.this::reinspectGarbageAfterGc, 100);
                    }

                    removeMessages(DO_GARBAGE_INSPECTION);
                    sendEmptyMessageDelayed(DO_GARBAGE_INSPECTION, GARBAGE_INSPECTION_INTERVAL);
                    break;

                case DO_HEAP_TRACK:
                    update();
                    removeMessages(DO_HEAP_TRACK);
                    sendEmptyMessageDelayed(DO_HEAP_TRACK, HEAP_TRACK_INTERVAL);
                    break;
            }
        }
    }
}
