/*
 * Copyright (C) 2015 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.performanceapp.tests;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.support.test.InstrumentationRegistry;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;

/**
 * To test the App launch performance on the given target package for the list of activities. It
 * launches the activities present in the target package the number of times in launch count or it
 * launches only the activities mentioned in custom activity list the launch count times and returns
 * the path to the files where the atrace logs are stored corresponding to each activity launch
 */
public class AppLaunchTests extends InstrumentationTestCase {

    private static final String TAG = "AppLaunchInstrumentation";
    private static final String TARGETPACKAGE = "targetpackage";
    private static final String ACTIVITYLIST = "activitylist";
    private static final String LAUNCHCOUNT = "launchcount";
    private static final String RECORDTRACE = "recordtrace";
    private static final String ATRACE_START = "atrace --async_start am view gfx";
    private static final String ATRACE_DUMP = "atrace --async_dump";
    private static final String ATRACE_STOP = "atrace --async_stop";
    private static final String FORCE_STOP = "am force-stop ";

    private Context mContext;
    private Bundle mResult;
    private String mTargetPackageName;
    private int mLaunchCount;
    private String mCustomActivityList;
    private PackageInfo mPackageInfo;
    private boolean mRecordTrace = true;
    private List<String> mActivityList;

    /**
     * {@inheritDoc}
     */
    @Override
    public void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getTargetContext();
        assertNotNull("Failed to get context", mContext);
        Bundle args = InstrumentationRegistry.getArguments();
        assertNotNull("Unable to get the args", args);
        mTargetPackageName = args.getString(TARGETPACKAGE);
        assertNotNull("Target package name not set", mTargetPackageName);
        mCustomActivityList = args.getString(ACTIVITYLIST);
        if (mCustomActivityList == null || mCustomActivityList.isEmpty()) {
            // Get full list of activities from the target package
            mActivityList = getActivityList("");
        } else {
            // Get only the user defined list of activities from the target package
            mActivityList = getActivityList(mCustomActivityList);
        }
        assertTrue("Activity List is empty", (mActivityList.size() > 0));
        mLaunchCount = Integer.parseInt(args.getString(LAUNCHCOUNT));
        assertTrue("Invalid Launch Count", mLaunchCount > 0);
        if (args.getString(RECORDTRACE) != null
                && args.getString(RECORDTRACE).equalsIgnoreCase("false")) {
            mRecordTrace = false;
        }
        mResult = new Bundle();
    }

    @MediumTest
    public void testAppLaunchPerformance() throws Exception {
        assertTrue("Cannot write in External File", isExternalStorageWritable());
        File root = Environment.getExternalStorageDirectory();
        assertNotNull("Unable to get the root of the external storage", root);
        File logsDir = new File(root, "atrace_logs");
        assertTrue("Unable to create the directory to store atrace logs", logsDir.mkdir());
        for (int count = 0; count < mLaunchCount; count++) {
            for (String activityName : mActivityList) {
                ComponentName cn = new ComponentName(mTargetPackageName,
                        activityName);
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
                intent.setComponent(cn);

                // Start the atrace
                if (mRecordTrace) {
                    assertNotNull(
                            "Unable to start atrace async",
                            getInstrumentation().getUiAutomation()
                                    .executeShellCommand(ATRACE_START));
                    // Sleep for 10 secs to make sure atrace command is started
                    Thread.sleep(10 * 1000);
                }

                // Launch the activity
                mContext.startActivity(intent);
                Thread.sleep(5 * 1000);

                // Dump atrace info and write it to file
                if (mRecordTrace) {
                    int processId = getProcessId(mTargetPackageName);
                    assertTrue("Not able to retrive the process id for the package:"
                            + mTargetPackageName, processId > 0);
                    String fileName = String.format("%s-%d-%d", activityName, count, processId);
                    ParcelFileDescriptor parcelFile =
                            getInstrumentation().getUiAutomation().executeShellCommand(ATRACE_DUMP);
                    assertNotNull("Unable to get the File descriptor to standard out",
                            parcelFile);
                    InputStream inputStream = new FileInputStream(parcelFile.getFileDescriptor());
                    File file = new File(logsDir, fileName);
                    FileOutputStream outputStream = new FileOutputStream(file);
                    try {
                        byte[] buffer = new byte[1024];
                        int length;
                        while ((length = inputStream.read(buffer)) > 0) {
                            outputStream.write(buffer, 0, length);
                        }
                    } catch (IOException e) {
                        Log.w(TAG, "Error writing atrace info to file", e);
                    }
                    inputStream.close();
                    outputStream.close();

                    // Stop the atrace
                    assertNotNull(
                            "Unable to stop the atrace",
                            getInstrumentation().getUiAutomation().executeShellCommand(ATRACE_STOP));

                    // To keep track of the activity name,list of atrace file name
                    registerTraceFileNames(activityName, fileName);
                }
                assertNotNull("Unable to stop recent activity launched",
                        getInstrumentation().getUiAutomation().executeShellCommand(
                                FORCE_STOP + mTargetPackageName));
                Thread.sleep(5 * 1000);
            }
        }
        getInstrumentation().sendStatus(0, mResult);
    }

    /**
     * Method to check if external storage is writable
     * @return
     */
    public boolean isExternalStorageWritable() {
        return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());
    }

    /**
     * Method to get list of activities present in given target package If customActivityList is
     * passed then include only those activities
     * @return list of activity names
     */
    private List<String> getActivityList(String customActivityList) {
        mActivityList = new ArrayList<String>();
        try {
            mPackageInfo = mContext.getPackageManager().getPackageInfo(
                    mTargetPackageName, 1);
            assertNotNull("Unable to get  the target package info", mPackageInfo);
        } catch (NameNotFoundException e) {
            fail(String.format("Target application: %s not found", mTargetPackageName));
        }
        for (ActivityInfo activityInfo : mPackageInfo.activities) {
            mActivityList.add(activityInfo.name);
        }
        if (!customActivityList.isEmpty()) {
            List<String> finalActivityList = new
                    ArrayList<String>();
            String customList[] = customActivityList.split(",");
            for (int count = 0; count < customList.length; count++) {
                if (mActivityList.contains(customList[count])) {
                    finalActivityList.add(customList[count]);
                } else {
                    fail(String.format("Activity: %s not present in the target package : %s ",
                            customList[count], mTargetPackageName));
                }
            }
            mActivityList = finalActivityList;
        }
        return mActivityList;
    }

    /**
     * Method to retrieve process id from the activity manager
     * @param processName
     * @return
     */
    private int getProcessId(String processName) {
        ActivityManager am = (ActivityManager) getInstrumentation()
                .getContext().getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningAppProcessInfo> appsInfo = am.getRunningAppProcesses();
        assertNotNull("Unable to retrieve running apps info", appsInfo);
        for (RunningAppProcessInfo appInfo : appsInfo) {
            if (appInfo.processName.equals(processName)) {
                return appInfo.pid;
            }
        }
        return -1;
    }

    /**
     * To add the process id to the result map
     * @param activityNamereturn
     * @return
     * @throws IOException
     */
    private void registerTraceFileNames(String activityName, String absPath)
            throws IOException {
        if (mResult.containsKey(activityName)) {
            String existingResult = (String) mResult.get(activityName);
            mResult.putString(activityName, existingResult + "," + absPath);
        } else {
            mResult.putString(activityName, "" + absPath);
        }
    }
}

