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

import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.ddmlib.Log;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.CollectingOutputReceiver;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.tradefed.testtype.IBuildReceiver;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.String;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Scanner;
import java.util.Set;

/**
 * Host-side SELinux tests.
 *
 * These tests analyze the policy file in use on the subject device directly or
 * run as the shell user to evaluate aspects of the state of SELinux on the test
 * device which otherwise would not be available to a normal apk.
 */
public class SELinuxHostTest extends DeviceTestCase {

    private File sepolicyAnalyze;
    private File checkSeapp;
    private File checkFc;
    private File aospSeappFile;
    private File aospFcFile;
    private File aospPcFile;
    private File aospSvcFile;
    private File devicePolicyFile;
    private File deviceSeappFile;
    private File deviceFcFile;
    private File devicePcFile;
    private File deviceSvcFile;

    /**
     * A reference to the device under test.
     */
    private ITestDevice mDevice;

    private File copyResourceToTempFile(String resName) throws IOException {
        InputStream is = this.getClass().getResourceAsStream(resName);
        File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
        FileOutputStream os = new FileOutputStream(tempFile);
        int rByte = 0;
        while ((rByte = is.read()) != -1) {
            os.write(rByte);
        }
        os.flush();
        os.close();
        tempFile.deleteOnExit();
        return tempFile;
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mDevice = getDevice();

        /* retrieve the sepolicy-analyze executable from jar */
        sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
        sepolicyAnalyze.setExecutable(true);

        /* retrieve the checkseapp executable from jar */
        checkSeapp = copyResourceToTempFile("/checkseapp");
        checkSeapp.setExecutable(true);

        /* retrieve the checkfc executable from jar */
        checkFc = copyResourceToTempFile("/checkfc");
        checkFc.setExecutable(true);

        /* obtain sepolicy file from running device */
        devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
        devicePolicyFile.deleteOnExit();
        mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
                devicePolicyFile.getAbsolutePath());

        /* obtain seapp_contexts file from running device */
        deviceSeappFile = File.createTempFile("seapp_contexts", ".tmp");
        deviceSeappFile.deleteOnExit();
        mDevice.executeAdbCommand("pull", "/seapp_contexts",
                deviceSeappFile.getAbsolutePath());

        /* obtain file_contexts file from running device */
        deviceFcFile = File.createTempFile("file_contexts", ".tmp");
        deviceFcFile.deleteOnExit();
        mDevice.executeAdbCommand("pull", "/file_contexts",
                deviceFcFile.getAbsolutePath());

        /* obtain property_contexts file from running device */
        devicePcFile = File.createTempFile("property_contexts", ".tmp");
        devicePcFile.deleteOnExit();
        mDevice.executeAdbCommand("pull", "/property_contexts",
                devicePcFile.getAbsolutePath());

        /* obtain service_contexts file from running device */
        deviceSvcFile = File.createTempFile("service_contexts", ".tmp");
        deviceSvcFile.deleteOnExit();
        mDevice.executeAdbCommand("pull", "/service_contexts",
                deviceSvcFile.getAbsolutePath());

        /* retrieve the AOSP *_contexts files from jar */
        aospSeappFile = copyResourceToTempFile("/general_seapp_contexts");
        aospFcFile = copyResourceToTempFile("/general_file_contexts");
        aospPcFile = copyResourceToTempFile("/general_property_contexts");
        aospSvcFile = copyResourceToTempFile("/general_service_contexts");
    }

    /**
     * Tests that all domains in the running policy file are in enforcing mode
     *
     * @throws Exception
     */
    public void testAllEnforcing() throws Exception {

        /* run sepolicy-analyze permissive check on policy file */
        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
                devicePolicyFile.getAbsolutePath(), "permissive");
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The following SELinux domains were found to be in permissive mode:\n"
                   + errorString, errorString.length() == 0);
    }

    /**
     * Asserts that specified type is not associated with the specified
     * attribute.
     *
     * @param attribute
     *  The attribute name.
     * @param type
     *  The type name.
     */
    private void assertNotInAttribute(String attribute, String badtype) throws Exception {
        /* run sepolicy-analyze attribute check on policy file */
        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
                devicePolicyFile.getAbsolutePath(), "attribute", attribute);
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String type;
        while ((type = result.readLine()) != null) {
            assertFalse("Attribute " + attribute + " includes " + type + "\n",
                        type.equals(badtype));
        }
    }

    /**
     * Tests that mlstrustedsubject does not include untrusted_app
     * and that mlstrustedobject does not include app_data_file.
     * This helps prevent circumventing the per-user isolation of
     * normal apps via levelFrom=user.
     *
     * @throws Exception
     */
    public void testMLSAttributes() throws Exception {
        assertNotInAttribute("mlstrustedsubject", "untrusted_app");
        assertNotInAttribute("mlstrustedobject", "app_data_file");
    }

    /**
     * Tests that the seapp_contexts file on the device is valid.
     *
     * @throws Exception
     */
    public void testValidSeappContexts() throws Exception {
        File OutputFile = File.createTempFile("seapp_output", ".tmp");
        OutputFile.deleteOnExit();

        /* run checkseapp on seapp_contexts */
        ProcessBuilder pb = new ProcessBuilder(checkSeapp.getAbsolutePath(),
                "-p", devicePolicyFile.getAbsolutePath(),
                deviceSeappFile.getAbsolutePath(),
                "-o", OutputFile.getAbsolutePath());
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The seapp_contexts file was invalid:\n"
                   + errorString, errorString.length() == 0);
    }

    /**
     * Asserts that the actual file contents starts with the expected file
     * contents.
     *
     * @param expectedFile
     *  The file with the expected contents.
     * @param actualFile
     *  The actual file being checked.
     */
    private void assertFileStartsWith(File expectedFile, File actualFile) throws Exception {
        BufferedReader expectedReader = new BufferedReader(new FileReader(expectedFile.getAbsolutePath()));
        BufferedReader actualReader = new BufferedReader(new FileReader(actualFile.getAbsolutePath()));
        String expectedLine, actualLine;
        while ((expectedLine = expectedReader.readLine()) != null) {
            actualLine = actualReader.readLine();
            assertEquals("Lines do not match:", expectedLine, actualLine);
        }
    }

    /**
     * Tests that the seapp_contexts file on the device contains
     * the standard AOSP entries.
     *
     * @throws Exception
     */
    public void testAospSeappContexts() throws Exception {
        assertFileStartsWith(aospSeappFile, deviceSeappFile);
    }

    /**
     * Tests that the file_contexts file on the device contains
     * the standard AOSP entries.
     *
     * @throws Exception
     */
    public void testAospFileContexts() throws Exception {
        assertFileStartsWith(aospFcFile, deviceFcFile);
    }

    /**
     * Tests that the property_contexts file on the device contains
     * the standard AOSP entries.
     *
     * @throws Exception
     */
    public void testAospPropertyContexts() throws Exception {
        assertFileStartsWith(aospPcFile, devicePcFile);
    }

    /**
     * Tests that the service_contexts file on the device contains
     * the standard AOSP entries.
     *
     * @throws Exception
     */
    public void testAospServiceContexts() throws Exception {
        assertFileStartsWith(aospSvcFile, deviceSvcFile);
    }

    /**
     * Tests that the file_contexts file on the device is valid.
     *
     * @throws Exception
     */
    public void testValidFileContexts() throws Exception {

        /* run checkfc on file_contexts */
        ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                devicePolicyFile.getAbsolutePath(),
                deviceFcFile.getAbsolutePath());
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The file_contexts file was invalid:\n"
                   + errorString, errorString.length() == 0);
    }

    /**
     * Tests that the property_contexts file on the device is valid.
     *
     * @throws Exception
     */
    public void testValidPropertyContexts() throws Exception {

        /* run checkfc -p on property_contexts */
        ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                "-p", devicePolicyFile.getAbsolutePath(),
                devicePcFile.getAbsolutePath());
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The property_contexts file was invalid:\n"
                   + errorString, errorString.length() == 0);
    }

    /**
     * Tests that the service_contexts file on the device is valid.
     *
     * @throws Exception
     */
    public void testValidServiceContexts() throws Exception {

        /* run checkfc -p on service_contexts */
        ProcessBuilder pb = new ProcessBuilder(checkFc.getAbsolutePath(),
                "-p", devicePolicyFile.getAbsolutePath(),
                devicePcFile.getAbsolutePath());
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The service_contexts file was invalid:\n"
                   + errorString, errorString.length() == 0);
    }

   /**
     * Tests that the policy defines no booleans (runtime conditional policy).
     *
     * @throws Exception
     */
    public void testNoBooleans() throws Exception {

        /* run sepolicy-analyze booleans check on policy file */
        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
                devicePolicyFile.getAbsolutePath(), "booleans");
        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
        pb.redirectErrorStream(true);
        Process p = pb.start();
        p.waitFor();
        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
        String line;
        StringBuilder errorString = new StringBuilder();
        while ((line = result.readLine()) != null) {
            errorString.append(line);
            errorString.append("\n");
        }
        assertTrue("The policy contained booleans:\n"
                   + errorString, errorString.length() == 0);
    }

    /**
     * Tests that important domain labels are being appropriately applied.
     */

    /**
     * Asserts that no processes are running in a domain.
     *
     * @param domain
     *  The domain or SELinux context to check.
     */
    private void assertDomainEmpty(String domain) throws DeviceNotAvailableException {
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
        String msg = "Expected no processes in SELinux domain \"" + domain + "\""
            + " Found: \"" + procs + "\"";
        assertNull(msg, procs);
    }

    /**
     * Asserts that a domain exists and that only one, well defined, process is
     * running in that domain.
     *
     * @param domain
     *  The domain or SELinux context to check.
     * @param executable
     *  The path of the executable or application package name.
     */
    private void assertDomainOne(String domain, String executable) throws DeviceNotAvailableException {
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
        List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);
        String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
            + " Found \"" + procs + "\"";
        assertNotNull(msg, procs);
        assertEquals(msg, 1, procs.size());

        msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
            + "Found: \"" + procs + "\"";
        assertEquals(msg, executable, procs.get(0).procTitle);

        msg = "Expected 1 process with executable \"" + executable + "\""
            + " Found \"" + procs + "\"";
        assertNotNull(msg, exeProcs);
        assertEquals(msg, 1, exeProcs.size());

        msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
            + "Found: \"" + procs + "\"";
        assertEquals(msg, domain, exeProcs.get(0).label);
    }

    /**
     * Asserts that a domain may exist. If a domain exists, the cardinality of
     * the domain is verified to be 1 and that the correct process is running in
     * that domain.
     *
     * @param domain
     *  The domain or SELinux context to check.
     * @param executable
     *  The path of the executable or application package name.
     */
    private void assertDomainZeroOrOne(String domain, String executable)
        throws DeviceNotAvailableException {
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
        List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(executable);

        if (procs != null) {
            String msg = "Expected 1 process in SELinux domain \"" + domain + "\""
            + " Found: \"" + procs + "\"";
            assertEquals(msg, 1, procs.size());

            msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
                + "Found: \"" + procs.get(0) + "\"";
            assertEquals(msg, executable, procs.get(0).procTitle);
        }

        if (exeProcs != null) {
            String msg = "Expected 1 process with executable \"" + executable + "\""
            + " Found: \"" + procs + "\"";
            assertEquals(msg, 1, exeProcs.size());

            msg = "Expected executable \"" + executable + "\" in SELinux domain \"" + domain + "\""
                + "Found: \"" + procs.get(0) + "\"";
            assertEquals(msg, domain, exeProcs.get(0).label);
        }
    }

    /**
     * Asserts that a domain must exist, and that the cardinality is greater
     * than or equal to 1.
     *
     * @param domain
     *  The domain or SELinux context to check.
     * @param executables
     *  The path of the allowed executables or application package names.
     */
    private void assertDomainN(String domain, String... executables)
        throws DeviceNotAvailableException {
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
        String msg = "Expected 1 or more processes in SELinux domain but found none.";
        assertNotNull(msg, procs);

        Set<String> execList = new HashSet<String>(Arrays.asList(executables));

        for (ProcessDetails p : procs) {
            msg = "Expected one of \"" + execList + "\" in SELinux domain \"" + domain + "\""
                + " Found: \"" + p + "\"";
            assertTrue(msg, execList.contains(p.procTitle));
        }

        for (String exe : executables) {
            List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);

            if (exeProcs != null) {
                for (ProcessDetails p : exeProcs) {
                    msg = "Expected executable \"" + exe + "\" in SELinux domain \""
                        + domain + "\"" + " Found: \"" + p + "\"";
                    assertEquals(msg, domain, p.label);
                }
            }
        }
    }

    /**
     * Asserts that a domain, if it exists, is only running the listed executables.
     *
     * @param domain
     *  The domain or SELinux context to check.
     * @param executables
     *  The path of the allowed executables or application package names.
     */
    private void assertDomainHasExecutable(String domain, String... executables)
        throws DeviceNotAvailableException {
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);

        if (procs != null) {
            Set<String> execList = new HashSet<String>(Arrays.asList(executables));

            for (ProcessDetails p : procs) {
                String msg = "Expected one of \"" + execList + "\" in SELinux domain \""
                    + domain + "\"" + " Found: \"" + p + "\"";
                assertTrue(msg, execList.contains(p.procTitle));
            }
        }

        for (String exe : executables) {
            List<ProcessDetails> exeProcs = ProcessDetails.getExeMap(mDevice).get(exe);

            if (exeProcs != null) {
                for (ProcessDetails p : exeProcs) {
                    String msg = "Expected executable \"" + exe + "\" in SELinux domain \""
                        + domain + "\"" + " Found: \"" + p + "\"";
                    assertEquals(msg, domain, p.label);
                }
            }
        }
    }

    /* Init is always there */
    public void testInitDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:init:s0", "/init");
    }

    /* Ueventd is always there */
    public void testUeventdDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:ueventd:s0", "/sbin/ueventd");
    }

    /* Devices always have healthd */
    public void testHealthdDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:healthd:s0", "/sbin/healthd");
    }

    /* Servicemanager is always there */
    public void testServicemanagerDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:servicemanager:s0", "/system/bin/servicemanager");
    }

    /* Vold is always there */
    public void testVoldDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:vold:s0", "/system/bin/vold");
    }

    /* netd is always there */
    public void testNetdDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:netd:s0", "/system/bin/netd");
    }

    /* Debuggerd is always there */
    public void testDebuggerdDomain() throws DeviceNotAvailableException {
        assertDomainN("u:r:debuggerd:s0", "/system/bin/debuggerd", "/system/bin/debuggerd64");
    }

    /* Surface flinger is always there */
    public void testSurfaceflingerDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:surfaceflinger:s0", "/system/bin/surfaceflinger");
    }

    /* Zygote is always running */
    public void testZygoteDomain() throws DeviceNotAvailableException {
        assertDomainN("u:r:zygote:s0", "zygote", "zygote64");
    }

    /* drm server is always present */
    public void testDrmServerDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:drmserver:s0", "/system/bin/drmserver");
    }

    /* Media server is always running */
    public void testMediaserverDomain() throws DeviceNotAvailableException {
        assertDomainN("u:r:mediaserver:s0", "media.log", "/system/bin/mediaserver");
    }

    /* Installd is always running */
    public void testInstalldDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:installd:s0", "/system/bin/installd");
    }

    /* keystore is always running */
    public void testKeystoreDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:keystore:s0", "/system/bin/keystore");
    }

    /* System server better be running :-P */
    public void testSystemServerDomain() throws DeviceNotAvailableException {
        assertDomainOne("u:r:system_server:s0", "system_server");
    }

    /*
     * Some OEMs do not use sdcardd so transient. Other OEMs have multiple sdcards
     * so they run the daemon multiple times.
     */
    public void testSdcarddDomain() throws DeviceNotAvailableException {
        assertDomainHasExecutable("u:r:sdcardd:s0", "/system/bin/sdcard");
    }

    /* Watchdogd may or may not be there */
    public void testWatchdogdDomain() throws DeviceNotAvailableException {
        assertDomainZeroOrOne("u:r:watchdogd:s0", "/sbin/watchdogd");
    }

    /* logd may or may not be there */
    public void testLogdDomain() throws DeviceNotAvailableException {
        assertDomainZeroOrOne("u:r:logd:s0", "/system/bin/logd");
    }

    /* lmkd may or may not be there */
    public void testLmkdDomain() throws DeviceNotAvailableException {
        assertDomainZeroOrOne("u:r:lmkd:s0", "/system/bin/lmkd");
    }

    /* Wifi may be off so cardinality of 0 or 1 is ok */
    public void testWpaDomain() throws DeviceNotAvailableException {
        assertDomainZeroOrOne("u:r:wpa:s0", "/system/bin/wpa_supplicant");
    }

    /*
     * Nothing should be running in this domain, cardinality test is all thats
     * needed
     */
    public void testInitShellDomain() throws DeviceNotAvailableException {
        assertDomainEmpty("u:r:init_shell:s0");
    }

    /*
     * Nothing should be running in this domain, cardinality test is all thats
     * needed
     */
    public void testRecoveryDomain() throws DeviceNotAvailableException {
        assertDomainEmpty("u:r:recovery:s0");
    }

    /*
     * Nothing should be running in this domain, cardinality test is all thats
     * needed
     */
    public void testSuDomain() throws DeviceNotAvailableException {
        assertDomainEmpty("u:r:su:s0");
    }

    /*
     * All kthreads should be in kernel context.
     */
    public void testKernelDomain() throws DeviceNotAvailableException {
        String domain = "u:r:kernel:s0";
        List<ProcessDetails> procs = ProcessDetails.getProcMap(mDevice).get(domain);
        if (procs != null) {
            for (ProcessDetails p : procs) {
                assertTrue("Non Kernel thread \"" + p + "\" found!", p.isKernel());
            }
        }
    }

    private static class ProcessDetails {
        public String label;
        public String user;
        public int pid;
        public int ppid;
        public String procTitle;

        private static HashMap<String, ArrayList<ProcessDetails>> procMap;
        private static HashMap<String, ArrayList<ProcessDetails>> exeMap;
        private static int kernelParentThreadpid = -1;

        ProcessDetails(String label, String user, int pid, int ppid, String procTitle) {
            this.label = label;
            this.user = user;
            this.pid = pid;
            this.ppid = ppid;
            this.procTitle = procTitle;
        }

        @Override
        public String toString() {
            return "label: " + label
                    + " user: " + user
                    + " pid: " + pid
                    + " ppid: " + ppid
                    + " cmd: " + procTitle;
        }


        private static void createProcMap(ITestDevice tDevice) throws DeviceNotAvailableException {

            /* take the output of a ps -Z to do our analysis */
            CollectingOutputReceiver psOut = new CollectingOutputReceiver();
            tDevice.executeShellCommand("ps -Z", psOut);
            String psOutString = psOut.getOutput();
            Pattern p = Pattern.compile(
                    "^([\\w_:]+)\\s+([\\w_]+)\\s+(\\d+)\\s+(\\d+)\\s+(\\p{Graph}+)$",
                    Pattern.MULTILINE);
            Matcher m = p.matcher(psOutString);
            procMap = new HashMap<String, ArrayList<ProcessDetails>>();
            exeMap = new HashMap<String, ArrayList<ProcessDetails>>();
            while(m.find()) {
                String domainLabel = m.group(1);
                String user = m.group(2);
                int pid = Integer.parseInt(m.group(3));
                int ppid = Integer.parseInt(m.group(4));
                String procTitle = m.group(5);
                ProcessDetails proc = new ProcessDetails(domainLabel, user, pid, ppid, procTitle);
                if (procMap.get(domainLabel) == null) {
                    procMap.put(domainLabel, new ArrayList<ProcessDetails>());
                }
                procMap.get(domainLabel).add(proc);
                if (procTitle.equals("kthreadd") && ppid == 0) {
                    kernelParentThreadpid = pid;
                }
                if (exeMap.get(procTitle) == null) {
                    exeMap.put(procTitle, new ArrayList<ProcessDetails>());
                }
                exeMap.get(procTitle).add(proc);
            }
        }

        public static HashMap<String, ArrayList<ProcessDetails>> getProcMap(ITestDevice tDevice)
                throws DeviceNotAvailableException{
            if (procMap == null) {
                createProcMap(tDevice);
            }
            return procMap;
        }

        public static HashMap<String, ArrayList<ProcessDetails>> getExeMap(ITestDevice tDevice)
                throws DeviceNotAvailableException{
            if (exeMap == null) {
                createProcMap(tDevice);
            }
            return exeMap;
        }

        public boolean isKernel() {
            return (pid == kernelParentThreadpid || ppid == kernelParentThreadpid);
        }
    }
}
