/*
 * Copyright (C) 2012 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.compatibilitytest;

import android.app.ActivityManager;
import android.app.ActivityManager.ProcessErrorStateInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Application Compatibility Test that launches an application and detects
 * crashes.
 */
@RunWith(AndroidJUnit4.class)
public class AppCompatibility {

    private static final String TAG = AppCompatibility.class.getSimpleName();
    private static final String PACKAGE_TO_LAUNCH = "package_to_launch";
    private static final String APP_LAUNCH_TIMEOUT_MSECS = "app_launch_timeout_ms";
    private static final String WORKSPACE_LAUNCH_TIMEOUT_MSECS = "workspace_launch_timeout_ms";
    private static final Set<String> DROPBOX_TAGS = new HashSet<>();
    static {
        DROPBOX_TAGS.add("SYSTEM_TOMBSTONE");
        DROPBOX_TAGS.add("system_app_anr");
        DROPBOX_TAGS.add("system_app_native_crash");
        DROPBOX_TAGS.add("system_app_crash");
        DROPBOX_TAGS.add("data_app_anr");
        DROPBOX_TAGS.add("data_app_native_crash");
        DROPBOX_TAGS.add("data_app_crash");
    }
    private static final int MAX_CRASH_SNIPPET_LINES = 20;
    private static final int MAX_NUM_CRASH_SNIPPET = 3;

    // time waiting for app to launch
    private int mAppLaunchTimeout = 7000;
    // time waiting for launcher home screen to show up
    private int mWorkspaceLaunchTimeout = 2000;

    private Context mContext;
    private ActivityManager mActivityManager;
    private PackageManager mPackageManager;
    private Bundle mArgs;
    private Instrumentation mInstrumentation;
    private String mLauncherPackageName;
    private IActivityController mCrashSupressor = new CrashSuppressor();
    private Map<String, List<String>> mAppErrors = new HashMap<>();

    @Before
    public void setUp() throws Exception {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mContext = InstrumentationRegistry.getTargetContext();
        mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
        mPackageManager = mContext.getPackageManager();
        mArgs = InstrumentationRegistry.getArguments();

        // resolve launcher package name
        Intent intent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);
        ResolveInfo resolveInfo = mPackageManager.resolveActivity(
                intent, PackageManager.MATCH_DEFAULT_ONLY);
        mLauncherPackageName = resolveInfo.activityInfo.packageName;
        Assert.assertNotNull("failed to resolve package name for launcher", mLauncherPackageName);
        Log.v(TAG, "Using launcher package name: " + mLauncherPackageName);

        // Parse optional inputs.
        String appLaunchTimeoutMsecs = mArgs.getString(APP_LAUNCH_TIMEOUT_MSECS);
        if (appLaunchTimeoutMsecs != null) {
            mAppLaunchTimeout = Integer.parseInt(appLaunchTimeoutMsecs);
        }
        String workspaceLaunchTimeoutMsecs = mArgs.getString(WORKSPACE_LAUNCH_TIMEOUT_MSECS);
        if (workspaceLaunchTimeoutMsecs != null) {
            mWorkspaceLaunchTimeout = Integer.parseInt(workspaceLaunchTimeoutMsecs);
        }
        mInstrumentation.getUiAutomation().setRotation(UiAutomation.ROTATION_FREEZE_0);

        // set activity controller to suppress crash dialogs and collects them by process name
        mAppErrors.clear();
        IActivityManager.Stub.asInterface(ServiceManager.checkService(Context.ACTIVITY_SERVICE))
            .setActivityController(mCrashSupressor, false);
    }

    @After
    public void tearDown() throws Exception {
        // unset activity controller
        IActivityManager.Stub.asInterface(ServiceManager.checkService(Context.ACTIVITY_SERVICE))
            .setActivityController(null, false);
        mInstrumentation.getUiAutomation().setRotation(UiAutomation.ROTATION_UNFREEZE);
    }

    /**
     * Actual test case that launches the package and throws an exception on the
     * first error.
     *
     * @throws Exception
     */
    @Test
    public void testAppStability() throws Exception {
        String packageName = mArgs.getString(PACKAGE_TO_LAUNCH);
        if (packageName != null) {
            Log.d(TAG, "Launching app " + packageName);
            Intent intent = getLaunchIntentForPackage(packageName);
            if (intent == null) {
                Log.w(TAG, String.format("Skipping %s; no launch intent", packageName));
                return;
            }
            long startTime = System.currentTimeMillis();
            launchActivity(packageName, intent);
            try {
                checkDropbox(startTime, packageName);
                if (mAppErrors.containsKey(packageName)) {
                    StringBuilder message = new StringBuilder("Error(s) detected for package: ")
                            .append(packageName);
                    List<String> errors = mAppErrors.get(packageName);
                    for (int i = 0; i < MAX_NUM_CRASH_SNIPPET && i < errors.size(); i++) {
                        String err = errors.get(i);
                        message.append("\n\n");
                        // limit the size of each crash snippet
                        message.append(truncate(err, MAX_CRASH_SNIPPET_LINES));
                    }
                    if (errors.size() > MAX_NUM_CRASH_SNIPPET) {
                        message.append(String.format("\n... %d more errors omitted ...",
                                errors.size() - MAX_NUM_CRASH_SNIPPET));
                    }
                    Assert.fail(message.toString());
                }
                // last check: see if app process is still running
                Assert.assertTrue("app package \"" + packageName + "\" no longer found in running "
                    + "tasks, but no explicit crashes were detected; check logcat for details",
                    processStillUp(packageName));
            } finally {
                returnHome();
            }
        } else {
            Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
                    " to specify the package to launch");
        }
    }

    /**
     * Truncate the text to at most the specified number of lines, and append a marker at the end
     * when truncated
     * @param text
     * @param maxLines
     * @return
     */
    private static String truncate(String text, int maxLines) {
        String[] lines = text.split("\\r?\\n");
        StringBuilder ret = new StringBuilder();
        for (int i = 0; i < maxLines && i < lines.length; i++) {
            ret.append(lines[i]);
            ret.append('\n');
        }
        if (lines.length > maxLines) {
            ret.append("... ");
            ret.append(lines.length - maxLines);
            ret.append(" more lines truncated ...\n");
        }
        return ret.toString();
    }

    /**
     * Check dropbox for entries of interest regarding the specified process
     * @param startTime if not 0, only check entries with timestamp later than the start time
     * @param processName the process name to check for
     */
    private void checkDropbox(long startTime, String processName) {
        DropBoxManager dropbox = (DropBoxManager) mContext
                .getSystemService(Context.DROPBOX_SERVICE);
        DropBoxManager.Entry entry = null;
        while (null != (entry = dropbox.getNextEntry(null, startTime))) {
            try {
                // only check entries with tag that's of interest
                String tag = entry.getTag();
                if (DROPBOX_TAGS.contains(tag)) {
                    String content = entry.getText(4096);
                    if (content != null) {
                        if (content.contains(processName)) {
                            addProcessError(processName, "dropbox:" + tag, content);
                        }
                    }
                }
                startTime = entry.getTimeMillis();
            } finally {
                entry.close();
            }
        }
    }

    private void returnHome() {
        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
        homeIntent.addCategory(Intent.CATEGORY_HOME);
        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // Send the "home" intent and wait 2 seconds for us to get there
        mContext.startActivity(homeIntent);
        try {
            Thread.sleep(mWorkspaceLaunchTimeout);
        } catch (InterruptedException e) {
            // ignore
        }
    }

    private Intent getLaunchIntentForPackage(String packageName) {
        UiModeManager umm = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
        boolean isLeanback = umm.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
        Intent intent = null;
        if (isLeanback) {
            intent = mPackageManager.getLeanbackLaunchIntentForPackage(packageName);
        } else {
            intent = mPackageManager.getLaunchIntentForPackage(packageName);
        }
        return intent;
    }

    /**
     * Launches and activity and queries for errors.
     *
     * @param packageName {@link String} the package name of the application to
     *            launch.
     * @return {@link Collection} of {@link ProcessErrorStateInfo} detected
     *         during the app launch.
     */
    private void launchActivity(String packageName, Intent intent) {
        Log.d(TAG, String.format("launching package \"%s\" with intent: %s",
                packageName, intent.toString()));

        // Launch Activity
        mContext.startActivity(intent);

        try {
            // artificial delay: in case app crashes after doing some work during launch
            Thread.sleep(mAppLaunchTimeout);
        } catch (InterruptedException e) {
            // ignore
        }
    }

    private void addProcessError(String processName, String errorType, String errorInfo) {
        // parse out the package name if necessary, for apps with multiple proceses
        String pkgName = processName.split(":", 2)[0];
        List<String> errors;
        if (mAppErrors.containsKey(pkgName)) {
            errors = mAppErrors.get(pkgName);
        }  else {
            errors = new ArrayList<>();
        }
        errors.add(String.format("### Type: %s, Details:\n%s", errorType, errorInfo));
        mAppErrors.put(pkgName, errors);
    }

    /**
     * Determine if a given package is still running.
     *
     * @param packageName {@link String} package to look for
     * @return True if package is running, false otherwise.
     */
    private boolean processStillUp(String packageName) {
        @SuppressWarnings("deprecation")
        List<RunningTaskInfo> infos = mActivityManager.getRunningTasks(100);
        for (RunningTaskInfo info : infos) {
            if (info.baseActivity.getPackageName().equals(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * An {@link IActivityController} that instructs framework to kill processes hitting crashes
     * directly without showing crash dialogs
     *
     */
    private class CrashSuppressor extends IActivityController.Stub {

        @Override
        public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
            Log.d(TAG, "activity starting: " + intent.getComponent().toShortString());
            return true;
        }

        @Override
        public boolean activityResuming(String pkg) throws RemoteException {
            Log.d(TAG, "activity resuming: " + pkg);
            return true;
        }

        @Override
        public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
                long timeMillis, String stackTrace) throws RemoteException {
            Log.d(TAG, "app crash: " + processName);
            addProcessError(processName, "crash", stackTrace);
            // don't show dialog
            return false;
        }

        @Override
        public int appEarlyNotResponding(String processName, int pid, String annotation)
                throws RemoteException {
            // ignore
            return 0;
        }

        @Override
        public int appNotResponding(String processName, int pid, String processStats)
                throws RemoteException {
            Log.d(TAG, "app ANR: " + processName);
            addProcessError(processName, "ANR", processStats);
            // don't show dialog
            return -1;
        }

        @Override
        public int systemNotResponding(String msg) throws RemoteException {
            // ignore
            return -1;
        }
    }
}
