/*
 * 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.performance.tests;

import com.android.tradefed.config.Option;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ByteArrayInputStreamSource;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.util.ProcessInfo;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.StreamUtil;

import org.junit.Assert;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Test to gather post launch memory details after launching app
 * that include app memory usage and system memory usage
 */
public class HermeticMemoryTest implements IDeviceTest, IRemoteTest {

    private static final String AM_START = "am start -n %s";
    private static final String PROC_MEMINFO = "cat /proc/meminfo";
    private static final String MEM_AVAILABLE = "cat /proc/meminfo| grep MemAvailable:";
    private static final String CACHED_PROCESSES = "dumpsys meminfo|awk '/Total PSS by category:"
            + "/{found=0} {if(found) print} /: Cached/{found=1}'|tr -d ' '";
    private static final Pattern PID_PATTERN = Pattern.compile("^.*pid(?<processid>[0-9]*).*$");
    private static final String DUMPSYS_PROCESS = "dumpsys meminfo %s |grep 'TOTAL'";
    private static final String DUMPSYS_MEMINFO = "dumpsys meminfo -a ";
    private static final String MAPS_INFO = "cat /proc/%d/maps";
    private static final String SMAPS_INFO = "cat /proc/%d/smaps";
    private static final String STATUS_INFO = "cat /proc/%d/status";
    private static final String NATIVE_HEAP = "Native";
    private static final String DALVIK_HEAP = "Dalvik";
    private static final String HEAP = "Heap";
    private static final String MEMTOTAL = "MemTotal";
    private static final String MEMFREE = "MemFree";
    private static final String CACHED = "Cached";
    private static final int NO_PROCESS_ID = -1;
    private static final String DROP_CACHE = "echo 3 > /proc/sys/vm/drop_caches";
    private static final String SEPARATOR ="\\s+";
    private static final String LINE_SEPARATOR = "\\n";


    @Option(name = "post-app-launch-delay",
            description = "The delay, between the app launch and the meminfo dump",
            isTimeVal = true)
    private long mPostAppLaunchDelay = 60;

    @Option(name = "component-name",
            description = "package/activity name to launch the activity")
    private String mComponentName = new String();

    @Option(name = "total-memory-kb",
            description = "Built in total memory of the device")
    private long mTotalMemory = 0;

    @Option(name = "reporting-key", description = "Reporting key is the unique identifier"
            + "used to report data in the dashboard.")
    private String mRuKey = "";

    private ITestDevice mTestDevice = null;
    private ITestInvocationListener mlistener = null;
    private Map<String, String> mMetrics = new HashMap<String, String> ();

    @Override
    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
        mlistener = listener;

        calculateFreeMem();

        String preMemInfo = mTestDevice.executeShellCommand(PROC_MEMINFO);

        if (!preMemInfo.isEmpty()) {

            uploadLogFile(preMemInfo, "BeforeLaunchProcMemInfo");
        } else {
            CLog.e("Not able to collect the /proc/meminfo before launching app");
        }

        Assert.assertTrue("Device built in memory in kb is mandatory.Use --total-memory-kb value"
                + "command line parameter",
                mTotalMemory != 0);
        RunUtil.getDefault().sleep(5000);
        mTestDevice.executeShellCommand(DROP_CACHE);
        RunUtil.getDefault().sleep(5000);
        Assert.assertTrue("Not a valid component name to start the activity",
                (mComponentName.split("/").length == 2));
        mTestDevice.executeShellCommand(String.format(AM_START, mComponentName));

        RunUtil.getDefault().sleep(mPostAppLaunchDelay);
        String postMemInfo = mTestDevice.executeShellCommand(PROC_MEMINFO);
        int processId = getProcessId();
        String dumpsysMemInfo = mTestDevice.executeShellCommand(
                String.format("%s %d", DUMPSYS_MEMINFO, processId));
        String mapsInfo = mTestDevice.executeShellCommand(
                String.format(MAPS_INFO, processId));
        String sMapsInfo = mTestDevice.executeShellCommand(
                String.format(SMAPS_INFO, processId));
        String statusInfo = mTestDevice.executeShellCommand(
                String.format(STATUS_INFO, processId));

        if (!postMemInfo.isEmpty()) {
            uploadLogFile(postMemInfo, "AfterLaunchProcMemInfo");
            parseProcInfo(postMemInfo);
        } else {
            CLog.e("Not able to collect the proc/meminfo after launching app");
        }

        if (NO_PROCESS_ID == processId) {
            CLog.e("Process Id not found for the activity launched");
        } else {
            if (!dumpsysMemInfo.isEmpty()) {
                uploadLogFile(dumpsysMemInfo, "DumpsysMemInfo");
                parseDumpsysInfo(dumpsysMemInfo);
            } else {
                CLog.e("Not able to collect the Dumpsys meminfo after launching app");
            }
            if (!mapsInfo.isEmpty()) {
                uploadLogFile(mapsInfo, "mapsInfo");
            } else {
                CLog.e("Not able to collect maps info after launching app");
            }
            if (!sMapsInfo.isEmpty()) {
                uploadLogFile(sMapsInfo, "smapsInfo");
            } else {
                CLog.e("Not able to collect smaps info after launching app");
            }
            if (!statusInfo.isEmpty()) {
                uploadLogFile(statusInfo, "statusInfo");
            } else {
                CLog.e("Not able to collect status info after launching app");
            }
        }

        reportMetrics(listener, mRuKey, mMetrics);

    }

    /**
     * Method to get the process id of the target package/activity name
     *
     * @return processId of the activity launched
     * @throws DeviceNotAvailableException
     */
    private int getProcessId() throws DeviceNotAvailableException {
        String pkgActivitySplit[] = mComponentName.split("/");
        if (pkgActivitySplit[0] != null) {
            ProcessInfo processData = mTestDevice.getProcessByName(pkgActivitySplit[0]);
            if (null != processData) {
                return processData.getPid();
            }
        }
        return NO_PROCESS_ID;
    }

    /**
     * Method to write the data to test logs.
     * @param data
     * @param fileName
     */
    private void uploadLogFile(String data, String fileName) {
        ByteArrayInputStreamSource inputStreamSrc = null;
        try {
            inputStreamSrc = new ByteArrayInputStreamSource(data.getBytes());
            mlistener.testLog(fileName, LogDataType.TEXT, inputStreamSrc);
        } finally {
            StreamUtil.cancel(inputStreamSrc);
        }
    }

    /**
     * Method to parse dalvik and heap info for launched app
     */
    private void parseDumpsysInfo(String dumpInfo) {
        String line[] = dumpInfo.split(LINE_SEPARATOR);
        for (int lineCount = 0; lineCount < line.length; lineCount++) {
            String dataSplit[] = line[lineCount].trim().split(SEPARATOR);
            if ((dataSplit[0].equalsIgnoreCase(NATIVE_HEAP) && dataSplit[1]
                    .equalsIgnoreCase(HEAP)) ||
                    (dataSplit[0].equalsIgnoreCase(DALVIK_HEAP) && dataSplit[1]
                            .equalsIgnoreCase(HEAP)) ||
                    dataSplit[0].equalsIgnoreCase("Total")) {
                if (dataSplit.length > 10) {
                    if (dataSplit[0].contains(NATIVE_HEAP)
                            || dataSplit[0].contains(DALVIK_HEAP)) {
                        mMetrics.put(dataSplit[0] + ":PSS_TOTAL", dataSplit[2]);
                        mMetrics.put(dataSplit[0] + ":SHARED_DIRTY", dataSplit[4]);
                        mMetrics.put(dataSplit[0] + ":PRIVATE_DIRTY", dataSplit[5]);
                        mMetrics.put(dataSplit[0] + ":HEAP_TOTAL", dataSplit[9]);
                        mMetrics.put(dataSplit[0] + ":HEAP_ALLOC", dataSplit[10]);
                    } else {
                        mMetrics.put(dataSplit[0] + ":PSS", dataSplit[1]);
                    }
                }
            }
        }
    }

    /**
     * Method to parse the system memory details
     */
    private void parseProcInfo(String memInfo) {
        String lineSplit[] = memInfo.split(LINE_SEPARATOR);
        long memTotal = 0;
        long memFree = 0;
        long cached = 0;
        for (int lineCount = 0; lineCount < lineSplit.length; lineCount++) {
            String line = lineSplit[lineCount].replace(":", "").trim();
            String dataSplit[] = line.split(SEPARATOR);
            if (dataSplit[0].equalsIgnoreCase(MEMTOTAL) ||
                    dataSplit[0].equalsIgnoreCase(MEMFREE) ||
                    dataSplit[0].equalsIgnoreCase(CACHED)) {
                if (dataSplit[0].equalsIgnoreCase(MEMTOTAL)) {
                    memTotal = Long.parseLong(dataSplit[1]);
                }
                if (dataSplit[0].equalsIgnoreCase(MEMFREE)) {
                    memFree = Long.parseLong(dataSplit[1]);
                }
                if (dataSplit[0].equalsIgnoreCase(CACHED)) {
                    cached = Long.parseLong(dataSplit[1]);
                }
                mMetrics.put("System_" + dataSplit[0], dataSplit[1]);
            }
        }
        mMetrics.put("System_Kernal_Firmware", String.valueOf((mTotalMemory - memTotal)));
        mMetrics.put("System_Framework_Apps", String.valueOf((memTotal - (memFree + cached))));
    }

    /**
     * Method to parse the free memory based on total memory available from proc/meminfo and
     * private dirty and private clean information of the cached processess
     * from dumpsys meminfo.
     */
    private void calculateFreeMem() throws DeviceNotAvailableException {
        String memAvailable[] = mTestDevice.executeShellCommand(MEM_AVAILABLE).split(SEPARATOR);
        int cacheProcDirty = Integer.parseInt(memAvailable[1]);

        String cachedProcesses = mTestDevice.executeShellCommand(CACHED_PROCESSES);
        String processes[] = cachedProcesses.split(LINE_SEPARATOR);
        for (String process : processes) {
            Matcher match = null;
            if (((match = matches(PID_PATTERN, process))) != null) {
                String processId = match.group("processid");
                String processInfoStr = mTestDevice.executeShellCommand(String.format(
                        DUMPSYS_PROCESS, processId));
                String processInfo[] = null;
                if (processInfoStr != null && !processInfoStr.isEmpty()) {
                    processInfo = processInfoStr.split(LINE_SEPARATOR);
                }
                if (null != processInfo && processInfo.length > 0) {
                    String procDetails[] = processInfo[0].trim().split(SEPARATOR);
                    cacheProcDirty = cacheProcDirty + Integer.parseInt(procDetails[2].trim())
                            + Integer.parseInt(procDetails[3]);
                }
            }
        }
        mMetrics.put("MemAvailable_CacheProcDirty", String.valueOf(cacheProcDirty));
    }

    /**
     * Report run metrics by creating an empty test run to stick them in
     *
     * @param listener the {@link ITestInvocationListener} of test results
     * @param runName the test name
     * @param metrics the {@link Map} that contains metrics for the given test
     */
    void reportMetrics(ITestInvocationListener listener, String runName,
            Map<String, String> metrics) {
        // Create an empty testRun to report the parsed runMetrics
        CLog.d("About to report metrics: %s", metrics);
        listener.testRunStarted(runName, 0);
        listener.testRunEnded(0, metrics);
    }

    /**
     * Checks whether {@code line} matches the given {@link Pattern}.
     *
     * @return The resulting {@link Matcher} obtained by matching the {@code line} against
     *         {@code pattern}, or null if the {@code line} does not match.
     */
    private static Matcher matches(Pattern pattern, String line) {
        Matcher ret = pattern.matcher(line);
        return ret.matches() ? ret : null;
    }

    @Override
    public void setDevice(ITestDevice device) {
        mTestDevice = device;
    }

    @Override
    public ITestDevice getDevice() {
        return mTestDevice;
    }
}
