/*
 * Copyright (C) 2021 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 android.cts.statsdatom.appexit;

import static android.app.AppExitReasonCode.REASON_OTHER;
import static android.app.AppExitReasonCode.REASON_PERMISSION_CHANGE;
import static android.app.AppExitSubReasonCode.SUBREASON_ISOLATED_NOT_NEEDED;
import static android.app.Importance.IMPORTANCE_CACHED;
import static android.app.Importance.IMPORTANCE_SERVICE;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import android.cts.statsdatom.lib.AtomTestUtils;
import android.cts.statsdatom.lib.ConfigUtils;
import android.cts.statsdatom.lib.DeviceUtils;
import android.cts.statsdatom.lib.ReportUtils;

import com.android.os.AtomsProto;
import com.android.os.StatsLog;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;

import java.util.List;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AppExitHostTest extends DeviceTestCase implements IBuildReceiver {
    private static final String TEST_PKG = "android.app.cts.appexit";
    private static final String HELPER_PKG1 = "android.externalservice.service";
    private static final String HELPER_PKG2 = "com.android.cts.launcherapps.simpleapp";
    private static final String TEST_APK = "CtsAppExitTestCases.apk";
    private static final String HELPER_APK1 = "CtsExternalServiceService.apk";
    private static final String HELPER_APK2 = "CtsSimpleApp.apk";
    private static final String TEST_CLASS = "android.app.cts.ActivityManagerAppExitInfoTest";
    private static final long APP_EXIT_INFO_STATSD_LOG_DEBOUNCE_MSEC = 15_000;
    private static final String PERM_PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
    private static final String PERM_READ_LOGS = "android.permission.READ_LOGS";

    private IBuildInfo mCtsBuild;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        assertThat(mCtsBuild).isNotNull();
        ConfigUtils.removeConfig(getDevice());
        ReportUtils.clearReports(getDevice());
        DeviceUtils.installTestApp(getDevice(), TEST_APK, TEST_PKG, mCtsBuild);
        DeviceUtils.installTestApp(getDevice(), HELPER_APK1, HELPER_PKG1, mCtsBuild);
        DeviceUtils.installTestApp(getDevice(), HELPER_APK2, HELPER_PKG2, mCtsBuild);
        Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
        getDevice().executeShellCommand("cmd deviceidle tempwhitelist -r " + HELPER_PKG1);
        getDevice().executeShellCommand("cmd deviceidle tempwhitelist -r " + HELPER_PKG2);
        getDevice().executeShellCommand("pm grant " + TEST_PKG + " " + PERM_PACKAGE_USAGE_STATS);
        getDevice().executeShellCommand("pm grant " + TEST_PKG + " " + PERM_READ_LOGS);
    }

    @Override
    protected void tearDown() throws Exception {
        ConfigUtils.removeConfig(getDevice());
        ReportUtils.clearReports(getDevice());
        getDevice().executeShellCommand("pm revoke " + TEST_PKG + " " + PERM_PACKAGE_USAGE_STATS);
        getDevice().executeShellCommand("pm revoke " + TEST_PKG + " " + PERM_READ_LOGS);
        DeviceUtils.uninstallTestApp(getDevice(), TEST_PKG);
        DeviceUtils.uninstallTestApp(getDevice(), HELPER_PKG1);
        DeviceUtils.uninstallTestApp(getDevice(), HELPER_PKG2);
        super.tearDown();
    }

    @Override
    public void setBuild(IBuildInfo buildInfo) {
        mCtsBuild = buildInfo;
    }

    public void testLogStatsdPermChanged() throws Exception {
        final String helperPackage = HELPER_PKG2;
        final int expectedUid = getAppUid(helperPackage);
        performLogStatsdTest("testPermissionChange", helperPackage, 1, appDied -> {
            assertThat(appDied.getUid()).isEqualTo(expectedUid);
            assertThat(appDied.getProcessName()).isEqualTo("");
            assertThat(appDied.getReason()).isEqualTo(REASON_PERMISSION_CHANGE);
            assertThat(appDied.getImportance()).isEqualTo(IMPORTANCE_CACHED);
            assertThat(appDied.getPss()).isAtLeast(0);
            assertThat(appDied.getRss()).isAtLeast(0);
        });
    }

    public void testLogStatsdOther() throws Exception {
        final String helperPackage = HELPER_PKG1;
        final int expectedUid = getAppUid(TEST_PKG);
        performLogStatsdTest("testOther", TEST_PKG, 2, appDied -> {
            assertThat(appDied.getUid()).isEqualTo(expectedUid);
            assertThat(appDied.getProcessName()).isEqualTo(
                    helperPackage + ":android.externalservice.service.ExternalServiceWithZygote");
            assertThat(appDied.getReason()).isEqualTo(REASON_OTHER);
            assertThat(appDied.getSubReason()).isEqualTo(SUBREASON_ISOLATED_NOT_NEEDED);
            assertThat(appDied.getImportance()).isEqualTo(IMPORTANCE_SERVICE);
        });
    }

    private void performLogStatsdTest(String testMethod, String targetPackage, int expectedSize,
            Consumer<AtomsProto.AppProcessDied> verifier) throws Exception {
        final int atomTag = AtomsProto.Atom.APP_PROCESS_DIED_FIELD_NUMBER;

        ConfigUtils.removeConfig(getDevice());
        ReportUtils.clearReports(getDevice());
        ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), targetPackage,
                atomTag, /* useUidAttributionChain= */ false);

        DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, TEST_CLASS, testMethod);
        Thread.sleep(APP_EXIT_INFO_STATSD_LOG_DEBOUNCE_MSEC);

        List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());

        assertThat(data).isNotNull();
        assertThat(data.size()).isEqualTo(expectedSize);

        verifier.accept(data.get(0).getAtom().getAppProcessDied());
    }

    private int getAppUid(String pkgName) throws Exception {
        final int currentUser = getDevice().getCurrentUser();
        final String uidLine = getDevice().executeShellCommand(
                "cmd package list packages -U --user " + currentUser + " " + pkgName);
        final Pattern pattern = Pattern.compile("package:" + pkgName + " uid:(\\d+)");
        final Matcher matcher = pattern.matcher(uidLine);
        assertWithMessage("Pkg not found: " + pkgName).that(matcher.find()).isTrue();
        final int appUid = Integer.parseInt(matcher.group(1));
        return appUid;
    }
}
