/*
 * Copyright (C) 2018 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.server.cts;

import com.android.server.am.ActiveInstrumentationProto;
import com.android.server.am.ActiveServicesProto;
import com.android.server.am.ActiveServicesProto.ServicesByUser;
import com.android.server.am.ActivityManagerServiceDumpBroadcastsProto;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto;
import com.android.server.am.ActivityManagerServiceDumpProcessesProto.LruProcesses;
import com.android.server.am.ActivityManagerServiceDumpServicesProto;
import com.android.server.am.AppErrorsProto;
import com.android.server.am.AppTimeTrackerProto;
import com.android.server.am.BroadcastQueueProto;
import com.android.server.am.BroadcastQueueProto.BroadcastSummary;
import com.android.server.am.BroadcastRecordProto;
import com.android.server.am.ConnectionRecordProto;
import com.android.server.am.GrantUriProto;
import com.android.server.am.ImportanceTokenProto;
import com.android.server.am.NeededUriGrantsProto;
import com.android.server.am.ProcessRecordProto;
import com.android.server.am.ServiceRecordProto;
import com.android.server.am.UidRecordProto;
import com.android.server.am.UriPermissionOwnerProto;
import com.android.server.am.VrControllerProto;

/**
 * Test to check that the activity manager service properly outputs its dump state.
 *
 * make -j32 CtsIncidentHostTestCases
 * cts-tradefed run singleCommand cts-dev -d --module CtsIncidentHostTestCases
 */
public class ActivityManagerIncidentTest extends ProtoDumpTestCase {

    private static final String TEST_BROADCAST = "com.android.mybroadcast";
    private static final String SYSTEM_PROC = "system";
    private static final int SYSTEM_UID = 1000;

    /**
     * Tests activity manager dumps broadcasts.
     */
    public void testDumpBroadcasts() throws Exception {
        getDevice().executeShellCommand("am broadcast -a " + TEST_BROADCAST);
        Thread.sleep(100);
        final ActivityManagerServiceDumpBroadcastsProto dump = getDump(
                ActivityManagerServiceDumpBroadcastsProto.parser(),
                "dumpsys activity --proto broadcasts");

        assertTrue(dump.getReceiverListCount() > 0);
        assertTrue(dump.getBroadcastQueueCount() > 0);
        assertTrue(dump.getStickyBroadcastsCount() > 0);

        boolean found = false;
mybroadcast:
        for (BroadcastQueueProto queue : dump.getBroadcastQueueList()) {
            for (BroadcastRecordProto record : queue.getHistoricalBroadcastsList()) {
                if (record.getIntentAction().equals(TEST_BROADCAST)) {
                    found = true;
                    break mybroadcast;
                }
            }
            for (BroadcastSummary summary : queue.getHistoricalBroadcastsSummaryList()) {
                if (summary.getIntent().getAction().equals(TEST_BROADCAST)) {
                    found = true;
                    break mybroadcast;
                }
            }
        }
        assertTrue(found);
        ActivityManagerServiceDumpBroadcastsProto.MainHandler mainHandler = dump.getHandler();
        assertTrue(mainHandler.getHandler().contains(
            "com.android.server.am.ActivityManagerService"));
    }

    /**
     * Tests activity manager dumps services.
     */
    public void testDumpServices() throws Exception {
        final ActivityManagerServiceDumpServicesProto dump = getDump(
                ActivityManagerServiceDumpServicesProto.parser(),
                "dumpsys activity --proto service");
        ActiveServicesProto activeServices = dump.getActiveServices();
        assertTrue(activeServices.getServicesByUsersCount() > 0);

        for (ServicesByUser perUserServices : activeServices.getServicesByUsersList()) {
            assertTrue(perUserServices.getServiceRecordsCount() >= 0);
            for (ServiceRecordProto service : perUserServices.getServiceRecordsList()) {
                assertFalse(service.getShortName().isEmpty());
                assertFalse(service.getPackageName().isEmpty());
                assertFalse(service.getProcessName().isEmpty());
                assertFalse(service.getAppinfo().getBaseDir().isEmpty());
                assertFalse(service.getAppinfo().getDataDir().isEmpty());
            }
        }

        verifyActivityManagerServiceDumpServicesProto(dump, PRIVACY_NONE);
    }

    static void verifyActivityManagerServiceDumpServicesProto(ActivityManagerServiceDumpServicesProto dump, final int filterLevel) throws Exception {
        for (ServicesByUser sbu : dump.getActiveServices().getServicesByUsersList()) {
            for (ServiceRecordProto srp : sbu.getServiceRecordsList()) {
                verifyServiceRecordProto(srp, filterLevel);
            }
        }
    }

    private static void verifyServiceRecordProto(ServiceRecordProto srp, final int filterLevel) throws Exception {
        if (filterLevel == PRIVACY_AUTO) {
            assertTrue(srp.getAppinfo().getBaseDir().isEmpty());
            assertTrue(srp.getAppinfo().getResDir().isEmpty());
            assertTrue(srp.getAppinfo().getDataDir().isEmpty());
        } else {
            assertFalse(srp.getAppinfo().getBaseDir().isEmpty());
            assertFalse(srp.getAppinfo().getDataDir().isEmpty());
        }
        for (ServiceRecordProto.StartItem si : srp.getDeliveredStartsList()) {
            verifyServiceRecordProtoStartItem(si, filterLevel);
        }
        for (ServiceRecordProto.StartItem si : srp.getPendingStartsList()) {
            verifyServiceRecordProtoStartItem(si, filterLevel);
        }
        for (ConnectionRecordProto crp : srp.getConnectionsList()) {
            verifyConnectionRecordProto(crp, filterLevel);
        }
    }

    private static void verifyServiceRecordProtoStartItem(ServiceRecordProto.StartItem si, final int filterLevel) throws Exception {
        verifyNeededUriGrantsProto(si.getNeededGrants(), filterLevel);
        verifyUriPermissionOwnerProto(si.getUriPermissions(), filterLevel);
    }

    private static void verifyNeededUriGrantsProto(NeededUriGrantsProto nugp, final int filterLevel) throws Exception {
        for (GrantUriProto gup : nugp.getGrantsList()) {
            verifyGrantUriProto(gup, filterLevel);
        }
    }

    private static void verifyUriPermissionOwnerProto(UriPermissionOwnerProto upop, final int filterLevel) throws Exception {
        if (filterLevel == PRIVACY_AUTO) {
            assertTrue(upop.getOwner().isEmpty());
        }
        for (GrantUriProto gup : upop.getReadPermsList()) {
            verifyGrantUriProto(gup, filterLevel);
        }
        for (GrantUriProto gup : upop.getWritePermsList()) {
            verifyGrantUriProto(gup, filterLevel);
        }
    }

    private static void verifyGrantUriProto(GrantUriProto gup, final int filterLevel) throws Exception {
        if (filterLevel == PRIVACY_AUTO) {
            assertTrue(gup.getUri().isEmpty());
        }
    }

    private static void verifyConnectionRecordProto(ConnectionRecordProto crp, final int filterLevel) throws Exception {
        for (ConnectionRecordProto.Flag f : crp.getFlagsList()) {
            assertTrue(ConnectionRecordProto.Flag.getDescriptor().getValues().contains(f.getValueDescriptor()));
        }
    }

    /**
     * Tests activity manager dumps processes.
     */
    public void testDumpProcesses() throws Exception {
        final ActivityManagerServiceDumpProcessesProto dump = getDump(
                ActivityManagerServiceDumpProcessesProto.parser(),
                "dumpsys activity --proto processes");

        assertTrue(dump.getProcsCount() > 0);
        boolean procFound = false;
        for (ProcessRecordProto proc : dump.getProcsList()) {
            if (proc.getProcessName().equals(SYSTEM_PROC) && proc.getUid() == SYSTEM_UID) {
                procFound = true;
                break;
            }
        }
        assertTrue(procFound);

        assertTrue(dump.getActiveUidsCount() > 0);
        boolean uidFound = false;
        for (UidRecordProto uid : dump.getActiveUidsList()) {
            if (uid.getUid() == SYSTEM_UID) {
                uidFound = true;
                break;
            }
        }
        assertTrue(uidFound);

        LruProcesses lruProcs = dump.getLruProcs();
        assertTrue(lruProcs.getSize() == lruProcs.getListCount());
        assertTrue(dump.getUidObserversCount() > 0);
        assertTrue(dump.getAdjSeq() > 0);
        assertTrue(dump.getLruSeq() > 0);

        verifyActivityManagerServiceDumpProcessesProto(dump, PRIVACY_NONE);
    }

    static void verifyActivityManagerServiceDumpProcessesProto(ActivityManagerServiceDumpProcessesProto dump, final int filterLevel) throws Exception {
        for (ActiveInstrumentationProto aip : dump.getActiveInstrumentationsList()) {
            verifyActiveInstrumentationProto(aip, filterLevel);
        }
        for (UidRecordProto urp : dump.getActiveUidsList()) {
            verifyUidRecordProto(urp, filterLevel);
        }
        for (UidRecordProto urp : dump.getValidateUidsList()) {
            verifyUidRecordProto(urp, filterLevel);
        }
        for (ImportanceTokenProto itp : dump.getImportantProcsList()) {
            verifyImportanceTokenProto(itp, filterLevel);
        }
        verifyAppErrorsProto(dump.getAppErrors(), filterLevel);
        verifyVrControllerProto(dump.getVrController(), filterLevel);
        verifyAppTimeTrackerProto(dump.getCurrentTracker(), filterLevel);
        if (filterLevel == PRIVACY_AUTO) {
            assertTrue(dump.getMemWatchProcesses().getDump().getUri().isEmpty());
        }
    }

    private static void verifyActiveInstrumentationProto(ActiveInstrumentationProto aip, final int filterLevel) throws Exception {
    }

    private static void verifyUidRecordProto(UidRecordProto urp, final int filterLevel) throws Exception {
        for (UidRecordProto.Change c : urp.getLastReportedChangesList()) {
            assertTrue(UidRecordProto.Change.getDescriptor().getValues().contains(c.getValueDescriptor()));
        }
        assertTrue(urp.getNumProcs() >= 0);
    }

    private static void verifyImportanceTokenProto(ImportanceTokenProto itp, final int filterLevel) throws Exception {
        if (filterLevel == PRIVACY_AUTO) {
            // The entire message is tagged as EXPLICIT, so even the pid should be stripped out.
            assertTrue(itp.getPid() == 0);
            assertTrue(itp.getToken().isEmpty());
            assertTrue(itp.getReason().isEmpty());
        }
    }

    private static void verifyAppErrorsProto(AppErrorsProto aep, final int filterLevel) throws Exception {
        assertTrue(aep.getNowUptimeMs() >= 0);
        if (filterLevel == PRIVACY_AUTO) {
            for (AppErrorsProto.BadProcess bp : aep.getBadProcessesList()) {
                for (AppErrorsProto.BadProcess.Entry e : bp.getEntriesList()) {
                    assertTrue(e.getLongMsg().isEmpty());
                    assertTrue(e.getStack().isEmpty());
                }
            }
        }
    }

    private static void verifyVrControllerProto(VrControllerProto vcp, final int filterLevel) throws Exception {
        for (VrControllerProto.VrMode vm : vcp.getVrModeList()) {
            assertTrue(VrControllerProto.VrMode.getDescriptor().getValues().contains(vm.getValueDescriptor()));
        }
    }

    private static void verifyAppTimeTrackerProto(AppTimeTrackerProto attp, final int filterLevel) throws Exception {
        assertTrue(attp.getTotalDurationMs() >= 0);
        for (AppTimeTrackerProto.PackageTime pt : attp.getPackageTimesList()) {
            assertTrue(pt.getDurationMs() >= 0);
        }
    }
}
