Merge "Add pre-upload style checker for cpp and java code"
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..7786266
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,17 @@
+// Copyright (C) 2017 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.
+
+subdirs = [
+    "api/tun",
+]
diff --git a/api/binder/Android.mk b/api/binder/Android.mk
new file mode 100644
index 0000000..e866f70
--- /dev/null
+++ b/api/binder/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelBinderTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/binder/AndroidTest.xml b/api/binder/AndroidTest.xml
new file mode 100644
index 0000000..f9e7cf4
--- /dev/null
+++ b/api/binder/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelBinderTest.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelBinderTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/binderSafeInterfaceTest/binderSafeInterfaceTest" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderSafeInterfaceTest/binderSafeInterfaceTest" />
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/binderLibTest/binderLibTest" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderLibTest/binderLibTest" />
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/binderDriverInterfaceTest/binderDriverInterfaceTest" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/binderDriverInterfaceTest/binderDriverInterfaceTest" />
+        <option name="binary-test-type" value="gtest"/>
+        <option name="test-timeout" value="10m"/>
+    </test>
+</configuration>
diff --git a/api/hwbinder/Android.mk b/api/hwbinder/Android.mk
new file mode 100644
index 0000000..c9fcaf8
--- /dev/null
+++ b/api/hwbinder/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelHwBinder
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/hwbinder/AndroidTest.xml b/api/hwbinder/AndroidTest.xml
new file mode 100644
index 0000000..8193b01
--- /dev/null
+++ b/api/hwbinder/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelBinderTest.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelHwBinder"/>
+        <option name="test-case-path" value="vts/testcases/kernel/api/hwbinder/VtsKernelHwBinderTest" />
+        <option name="test-timeout" value="1m"/>
+    </test>
+</configuration>
diff --git a/api/hwbinder/VtsKernelHwBinderTest.py b/api/hwbinder/VtsKernelHwBinderTest.py
new file mode 100644
index 0000000..8fd24e0
--- /dev/null
+++ b/api/hwbinder/VtsKernelHwBinderTest.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+HWBINDER_PATH = "/dev/hwbinder"
+
+class VtsKernelHwBinderTest(base_test.BaseTestClass):
+    """Test case to validate existence of hwbinder node.
+    """
+
+    def setUpClass(self):
+        self.dut = self.registerController(android_device)[0]
+        self.dut.shell.InvokeTerminal(
+            "VtsKernelHwBinderTest")  # creates a remote shell instance.
+        self.shell = self.dut.shell.VtsKernelHwBinderTest
+
+    def testHwbinderExistence(self):
+        """Checks that hwbinder node exists.
+        """
+        logging.info("Testing existence of %s", HWBINDER_PATH)
+        asserts.assertTrue(
+            file_utils.Exists(HWBINDER_PATH, self.shell),
+            "%s: File does not exist." % HWBINDER_PATH)
+
+        try:
+            permissions = file_utils.GetPermission(HWBINDER_PATH, self.shell)
+            asserts.assertTrue(file_utils.IsReadWrite(permissions),
+                               "%s: File has invalid permissions (%s)" %
+                               (HWBINDER_PATH, permissions))
+        except (ValueError, IOError) as e:
+            asserts.fail("Failed to assert permissions: %s" % str(e))
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/api/hwbinder/__init__.py b/api/hwbinder/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/hwbinder/__init__.py
diff --git a/api/netd/Android.mk b/api/netd/Android.mk
new file mode 100644
index 0000000..757dffe
--- /dev/null
+++ b/api/netd/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelNetdTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/netd/AndroidTest.xml b/api/netd/AndroidTest.xml
new file mode 100644
index 0000000..fa6ec48
--- /dev/null
+++ b/api/netd/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelNetdTest.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelNetdTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/netd_integration_test/netd_integration_test" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/netd_integration_test/netd_integration_test" />
+        <option name="binary-test-type" value="gtest"/>
+        <option name="test-timeout" value="10m"/>
+    </test>
+</configuration>
diff --git a/api/proc/AndroidTest.xml b/api/proc/AndroidTest.xml
index e7fc357..ba6183d 100644
--- a/api/proc/AndroidTest.xml
+++ b/api/proc/AndroidTest.xml
@@ -18,6 +18,7 @@
         <option name="push-group" value="HostDrivenTest.push" />
     </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+        <option name="dep-module" value="parse" />
         <option name="dep-module" value="ply" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
diff --git a/api/proc/KernelProcFileApiTest.py b/api/proc/KernelProcFileApiTest.py
index 660f976..c62cecd 100644
--- a/api/proc/KernelProcFileApiTest.py
+++ b/api/proc/KernelProcFileApiTest.py
@@ -15,68 +15,64 @@
 # limitations under the License.
 #
 
-import gzip
 import logging
-import os
-import shutil
-import tempfile
 
 from vts.runners.host import asserts
 from vts.runners.host import base_test
 from vts.runners.host import const
 from vts.runners.host import test_runner
-from vts.testcases.kernel.api.proc import required_kernel_configs as configs
-from vts.utils.python.controllers import android_device
 
-from ProcMemInfoTest import ProcMemInfoTest
-from ProcZoneInfoTest import ProcZoneInfoTest
-from ProcShowUidStatTest import ProcShowUidStatTest
-from ProcCpuInfoTest import ProcCpuInfoTest
-from ProcStatTest import ProcStatTest
-from ProcVmallocInfoTest import ProcVmallocInfoTest
-from ProcRemoveUidRangeTest import ProcRemoveUidRangeTest
-from ProcQtaguidCtrlTest import ProcQtaguidCtrlTest
-from ProcMapsTest import ProcMapsTest
-from ProcSimpleFileTests import ProcKptrRestrictTest
-from ProcSimpleFileTests import ProcMmapMinAddrTest
-from ProcSimpleFileTests import ProcMmapRndBitsTest
-from ProcSimpleFileTests import ProcMmapRndCompatBitsTest
-from ProcSimpleFileTests import ProcOverCommitMemoryTest
-from ProcSimpleFileTests import ProcRandomizeVaSpaceTest
+from vts.testcases.kernel.api.proc import ProcCmdlineTest
+from vts.testcases.kernel.api.proc import ProcCpuInfoTest
+from vts.testcases.kernel.api.proc import ProcKmsgTest
+from vts.testcases.kernel.api.proc import ProcMapsTest
+from vts.testcases.kernel.api.proc import ProcMemInfoTest
+from vts.testcases.kernel.api.proc import ProcModulesTest
+from vts.testcases.kernel.api.proc import ProcMountsTest
+from vts.testcases.kernel.api.proc import ProcQtaguidCtrlTest
+from vts.testcases.kernel.api.proc import ProcRemoveUidRangeTest
+from vts.testcases.kernel.api.proc import ProcSimpleFileTests
+from vts.testcases.kernel.api.proc import ProcShowUidStatTest
+from vts.testcases.kernel.api.proc import ProcStatTest
+from vts.testcases.kernel.api.proc import ProcVersionTest
+from vts.testcases.kernel.api.proc import ProcVmallocInfoTest
+from vts.testcases.kernel.api.proc import ProcZoneInfoTest
+
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
 
 TEST_OBJECTS = {
-    ProcMemInfoTest(),
-    ProcZoneInfoTest(),
-    ProcShowUidStatTest(),
-    ProcCpuInfoTest(),
-    ProcStatTest(),
-    ProcVmallocInfoTest(),
-    ProcKptrRestrictTest(),
-    ProcRandomizeVaSpaceTest(),
-    ProcMmapMinAddrTest(),
-    ProcMmapRndBitsTest(),
-    ProcMmapRndCompatBitsTest(),
-    ProcOverCommitMemoryTest(),
-    ProcRemoveUidRangeTest(),
-    ProcQtaguidCtrlTest(),
-    ProcMapsTest(),
+    ProcCmdlineTest.ProcCmdlineTest(),
+    ProcCpuInfoTest.ProcCpuInfoTest(),
+    ProcKmsgTest.ProcKmsgTest(),
+    ProcSimpleFileTests.ProcKptrRestrictTest(),
+    ProcMapsTest.ProcMapsTest(),
+    ProcMemInfoTest.ProcMemInfoTest(),
+    ProcSimpleFileTests.ProcMmapMinAddrTest(),
+    ProcSimpleFileTests.ProcMmapRndBitsTest(),
+    ProcSimpleFileTests.ProcMmapRndCompatBitsTest(),
+    ProcModulesTest.ProcModulesTest(),
+    ProcMountsTest.ProcMountsTest(),
+    ProcSimpleFileTests.ProcOverCommitMemoryTest(),
+    ProcQtaguidCtrlTest.ProcQtaguidCtrlTest(),
+    ProcSimpleFileTests.ProcRandomizeVaSpaceTest(),
+    ProcRemoveUidRangeTest.ProcRemoveUidRangeTest(),
+    ProcShowUidStatTest.ProcShowUidStatTest(),
+    ProcStatTest.ProcStatTest(),
+    ProcVersionTest.ProcVersionTest(),
+    ProcVmallocInfoTest.ProcVmallocInfoTest(),
+    ProcZoneInfoTest.ProcZoneInfoTest(),
 }
 
+
 class KernelProcFileApiTest(base_test.BaseTestClass):
-    """Test cases which check content of proc files.
-
-    Attributes:
-        _temp_dir: The temporary directory to which /proc/config.gz is copied.
-    """
-
-    PROC_FILE_PATH = "/proc/config.gz"
+    """Test cases which check content of proc files."""
 
     def setUpClass(self):
         self.dut = self.registerController(android_device)[0]
         self.dut.shell.InvokeTerminal(
             "KernelApiTest")  # creates a remote shell instance.
         self.shell = self.dut.shell.KernelApiTest
-        self._temp_dir = tempfile.mkdtemp()
 
     def runProcFileTest(self, test_object):
         """Reads from the file and checks that it parses and the content is valid.
@@ -84,11 +80,19 @@
         Args:
             test_object: inherits KernelProcFileTestBase, contains the test functions
         """
-        logging.info("Testing format of %s" % (test_object.get_path()))
+        filepath = test_object.get_path()
+        file_utils.assertPermissionsAndExistence(
+            self.shell, filepath, test_object.get_permission_checker())
+
+        logging.info("Testing format of %s", filepath)
+
         asserts.assertTrue(
             test_object.prepare_test(self.shell), "Setup failed!")
 
-        file_content = self.ReadFileContent(test_object.get_path())
+        if not test_object.test_format():
+            return
+
+        file_content = self.ReadFileContent(filepath)
         try:
             parse_result = test_object.parse_contents(file_content)
         except SyntaxError as e:
@@ -98,9 +102,10 @@
 
     def generateProcFileTests(self):
         """Run all proc file tests."""
-        self.runGeneratedTests(test_func=self.runProcFileTest,
-                settings=TEST_OBJECTS,
-                name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
+        self.runGeneratedTests(
+            test_func=self.runProcFileTest,
+            settings=TEST_OBJECTS,
+            name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
 
     def ReadFileContent(self, filepath):
         """Read the content of a file and perform assertions.
@@ -113,8 +118,6 @@
         """
         cmd = "cat %s" % filepath
         results = self.shell.Execute(cmd)
-        logging.info("%s: Shell command '%s' results: %s", filepath, cmd,
-                     results)
 
         # checks the exit code
         asserts.assertEqual(
@@ -123,44 +126,6 @@
 
         return results[const.STDOUT][0]
 
-    def testCheckConfigs(self):
-        """Ensures all options from android-base.cfg are enabled."""
-        self.dut.adb.pull("%s %s" % (self.PROC_FILE_PATH, self._temp_dir))
-        logging.info("Adb pull %s to %s", self.PROC_FILE_PATH, self._temp_dir)
-
-        localpath = os.path.join(self._temp_dir, "config.gz")
-        with gzip.open(localpath, 'rb') as f:
-            device_config_lines = [line.rstrip("\n") for line in f.readlines()]
-
-        device_configs = dict()
-        for line in device_config_lines:
-            if line == "" or line.startswith("#"):
-                continue
-            config_name, config_state = line.split("=", 1)
-            device_configs[config_name] = config_state
-
-        should_be_enabled = []
-        should_not_be_set = []
-        for config_name, config_state in configs.CONFIGS.iteritems():
-            if (config_state == "y" and
-                (config_name not in device_configs or
-                 device_configs[config_name] not in ("y", "m"))):
-                should_be_enabled.append(config_name)
-            elif config_state == "n" and config_name in device_configs:
-                should_not_be_set.append(config_name + "=" +
-                                         device_configs[config_name])
-
-        asserts.assertTrue(
-            len(should_be_enabled) == 0 and len(should_not_be_set) == 0,
-            ("The following kernel configs should be enabled: [%s].\n"
-             "The following kernel configs should not be set: [%s]") %
-            (", ".join(should_be_enabled), ", ".join(should_not_be_set)))
-
-    def tearDownClass(self):
-        """Deletes the temporary directory."""
-        logging.info("Delete %s", self._temp_dir)
-        shutil.rmtree(self._temp_dir)
-
 
 if __name__ == "__main__":
     test_runner.main()
diff --git a/api/proc/KernelProcFileTestBase.py b/api/proc/KernelProcFileTestBase.py
index ce4fe54..0b0ed02 100644
--- a/api/proc/KernelProcFileTestBase.py
+++ b/api/proc/KernelProcFileTestBase.py
@@ -16,9 +16,14 @@
 #
 
 import os
+import parse
 import sys
+
+from abc import ABCMeta
+from abc import abstractmethod
 from ply import lex
 from ply import yacc
+from vts.utils.python.file import file_utils
 
 
 def repeat_rule(to_repeat, zero_ok=False):
@@ -68,6 +73,8 @@
     Child class should also specify a `start` variable to give the starting rule.
     """
 
+    __metaclass__ = ABCMeta
+
     def t_HEX_LITERAL(self, t):
         r'0x[a-f0-9]+'
         t.value = int(t.value, 0)
@@ -129,29 +136,75 @@
         self.parser = yacc.yacc(module=self, write_tables=False, \
                 errorlog=yacc.PlyLogger(sys.stderr)) #open(os.devnull, 'w')))
 
-    def parse_contents(self, file_contents):
+    def parse_line(self, rule, line, custom={}):
+        """Parse a line of text with the parse library.
+
+        Args:
+            line: string, a line of text
+            rule: string, a format rule. See parse documentation
+            custom: dict, maps to custom type conversion functions
+
+        Returns:
+            list, information parsed from the line
+
+        Raises:
+            SyntaxError: if the line could not be parsed.
         """
-        Using the internal parser, parse the contents and return a structure
-        constructed according to the parsing rules
+        parsed = parse.parse(rule, line, custom)
+        if parsed is None:
+            raise SyntaxError("Failed to parse line %s according to rule %s" % (line, rule))
+        return list(parsed)
+
+    def parse_contents(self, file_contents):
+        """Using the internal parser, parse the contents.
+
+        Args:
+            file_contents: string, entire contents of a file
+
+        Returns:
+            list, a parsed representation of the file
+
+        Raises:
+            SyntaxError: if the file could not be parsed
         """
         return self.parser.parse(file_contents, lexer=self.lexer)
 
+    @abstractmethod
     def get_path(self):
-        """
-        Return the full path of this proc file.
-        """
-        return ""
+        """Returns the full path of this proc file (string)."""
+        pass
 
     def prepare_test(self, shell):
-        """
-        Performs any actions necessary before testing the proc file.
-        Return True if successful.
+        """Performs any actions necessary before testing the proc file.
+
+        Args:
+            shell: shell object, for preparation that requires device access
+
+        Returns:
+            boolean, True if successful.
         """
         return True
 
     def result_correct(self, parse_result):
-        """
-        Return True if the parsed result meets the requirements for the
-        proc file.
+        """Returns: True if the parsed result meets the requirements (boolean)."""
+        return True
+
+    def test_format(self):
+        """Returns:
+            boolean, True if the file should be read and its format tested.
+                     False if only the existence and permission should be tested.
         """
         return True
+
+    def get_permission_checker(self):
+        """Gets the function handle to use for validating file permissions.
+
+        Return the function that will check if the permissions are correct.
+        By default, return the IsReadOnly function from file_utils.
+
+        Returns:
+            function which takes one argument (the unix file permission bits
+            in octal format) and returns True if the permissions are correct,
+            False otherwise.
+        """
+        return file_utils.IsReadOnly
diff --git a/api/proc/ProcCmdlineTest.py b/api/proc/ProcCmdlineTest.py
new file mode 100644
index 0000000..8338cfa
--- /dev/null
+++ b/api/proc/ProcCmdlineTest.py
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcCmdlineTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/cmdline contains arguments passed to the kernel.'''
+
+    def parse_contents(self, contents):
+        if len(contents) == 0 or contents[-1] != '\n':
+            raise SyntaxError("missing newline")
+        return contents[:-1].split(' ')
+
+    def get_path(self):
+        return "/proc/cmdline"
diff --git a/api/proc/ProcCpuInfoTest.py b/api/proc/ProcCpuInfoTest.py
index b18d50c..eb3b50b 100644
--- a/api/proc/ProcCpuInfoTest.py
+++ b/api/proc/ProcCpuInfoTest.py
@@ -14,8 +14,8 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
 
 
 class ProcCpuInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
diff --git a/api/proc/ProcKmsgTest.py b/api/proc/ProcKmsgTest.py
new file mode 100644
index 0000000..b0d6c9e
--- /dev/null
+++ b/api/proc/ProcKmsgTest.py
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcKmsgTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/kmsg shows kernel messages in real time.'''
+
+    def test_format(self):
+        return False
+
+    def get_path(self):
+        return '/proc/kmsg'
diff --git a/api/proc/ProcMapsTest.py b/api/proc/ProcMapsTest.py
index 7ccfee4..c981faa 100644
--- a/api/proc/ProcMapsTest.py
+++ b/api/proc/ProcMapsTest.py
@@ -14,45 +14,57 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from parse import with_pattern
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
 
 
+@with_pattern(r'[0-9a-f]{8,}')
+def token_addr(text):
+    return int(text, 16)
+
+@with_pattern(r'[0-9a-f]{2,5}')
+def token_mm(text):
+    return int(text, 16)
+
+@with_pattern(r'[0-9]+')
+def token_lu(text):
+    return int(text)
+
+@with_pattern(r'[^\n^\0]*')
+def token_path(text):
+    return text.strip()
+
+@with_pattern(r'[r-]')
+def token_rbit(text):
+    return text
+
+@with_pattern(r'[w-]')
+def token_wbit(text):
+    return text
+
+@with_pattern(r'[x-]')
+def token_xbit(text):
+    return text
+
+@with_pattern(r'[sp]')
+def token_spbit(text):
+    return text
+
 class ProcMapsTest(KernelProcFileTestBase.KernelProcFileTestBase):
     '''/proc/self/maps provides currently mapped memory regions and permissions.'''
 
-    start = 'lines'
-
-    t_STRING = literal_token(r'[a-zA-Z\(\)_\-0-9@]+')
-    t_PATH = r'/[^\0^\n]*'
-    t_BRACKET_ITEM = r'\[[^\0^\n]*\]'
-    t_DASH = r'-'
-
-    t_ignore = r' '
-
-    p_lines = repeat_rule('line')
-
-    def p_line(self, p):
-        'line : STRING STRING STRING STRING COLON STRING STRING source NEWLINE'
-        rng = p[1].split('-')
-        try:
-            if len(rng) != 2:
-                print 'Invalid address range format!'
-                raise SyntaxError
-            p[0] = [int(rng[0], 16), int(rng[1], 16), p[2], int(p[3], 16), int(p[4], 16),\
-                    int(p[6], 16), int(p[7]), p[8]]
-        except ValueError:
-            print 'Invalid number!'
-            raise SyntaxError
-
-    def p_source(self, p):
-        '''source : PATH
-                  | BRACKET_ITEM
-                  | empty'''
-        if p[1] is None:
-            p[0] = []
-        else:
-            p[0] = p[1]
+    def parse_contents(self, contents):
+        result = []
+        lines = contents.split('\n')
+        if lines[-1] != '':
+            raise SyntaxError("missing final newline")
+        for line in lines[:-1]:
+            parsed = self.parse_line(
+                    "{:addr}-{:addr} {:rbit}{:wbit}{:xbit}{:spbit} {:addr} {:mm}:{:mm} {:lu}{:path}",
+                line, dict(mm=token_mm, addr=token_addr, lu=token_lu, path=token_path,
+                    rbit=token_rbit, wbit=token_wbit, xbit=token_xbit, spbit=token_spbit))
+            result.append(parsed)
+        return result
 
     def get_path(self):
         return "/proc/self/maps"
diff --git a/api/proc/ProcMemInfoTest.py b/api/proc/ProcMemInfoTest.py
index f0588ad..9182d93 100644
--- a/api/proc/ProcMemInfoTest.py
+++ b/api/proc/ProcMemInfoTest.py
@@ -14,18 +14,27 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+import logging
 
+from parse import with_pattern
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+@with_pattern(r'[^ ^\t^\n^:^\0]+')
+def token_name(text):
+    return text
+
+@with_pattern(r'[ ]*[0-9]+')
+def token_lu(text):
+    return int(text)
 
 class ProcMemInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    """
-    /proc/meminfo reports statistics about memory usage on the system.
+    '''/proc/meminfo reports statistics about memory usage on the system.
 
     No new fields should be added to the upstream implementation.
-    """
+    '''
 
-    ALLOWED_FIELDS = {
+    REQUIRED_FIELDS = {
         "MemTotal",
         "MemFree",
         "MemAvailable",
@@ -62,20 +71,21 @@
         "VmallocChunk",
     }
 
-    t_KB = literal_token(r'kB')
-
-    start = 'lines'
-    p_lines = repeat_rule('line')
-
-    def p_line(self, p):
-        'line : STRING COLON SPACEs NUMBER SPACE KB NEWLINE'
-        p[0] = [p[1], p[4]]
+    def parse_contents(self, contents):
+        lines = contents.split('\n')
+        if lines[-1] != '':
+            raise SyntaxError("missing final newline")
+        return [self.parse_line("{:name}: {:lu} kB", line, dict(name=token_name, lu=token_lu))
+                for line in lines[:-1]]
 
     def result_correct(self, parse_result):
+        required_fields = self.REQUIRED_FIELDS.copy()
         for line in parse_result:
-            if line[0] not in self.ALLOWED_FIELDS:
-                print "'%s' is an illegal field" % line[0]
-                return False
+            if line[0] in required_fields:
+                required_fields.remove(line[0])
+        if len(required_fields) > 0:
+            logging.error("Required fields not present: %s", str(required_fields))
+            return False
         return True
 
     def get_path(self):
diff --git a/api/proc/ProcModulesTest.py b/api/proc/ProcModulesTest.py
new file mode 100644
index 0000000..d877ad9
--- /dev/null
+++ b/api/proc/ProcModulesTest.py
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2017 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.
+#
+
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcModulesTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/modules contains information about loaded kernel modules.'''
+
+    def parse_contents(self, contents):
+        return ''
+
+    def result_correct(self, parse_result):
+        return True
+
+    def get_path(self):
+        return "/proc/modules"
diff --git a/api/proc/ProcMountsTest.py b/api/proc/ProcMountsTest.py
new file mode 100644
index 0000000..da0ce0b
--- /dev/null
+++ b/api/proc/ProcMountsTest.py
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
+
+
+class ProcMountsTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/self/mounts lists the mounted filesystems.
+
+    /proc/mounts must symlink to this file.'''
+
+    def parse_contents(self, contents):
+        if len(contents) == 0 or contents[-1] != '\n':
+            raise SyntaxError('Missing final newline')
+        result = []
+        for line in contents.split('\n')[:-1]:
+            parsed = line.split(' ')
+            parsed[3] = parsed[3].split(',')
+            result.append(parsed)
+        return result
+
+    def result_correct(self, parse_results):
+        for line in parse_results:
+            if len(line[3]) < 1 or line[3][0] not in {'rw', 'ro'}:
+                logging.error("First attribute must be rw or ro")
+                return False
+            if line[4] != '0' or line[5] != '0':
+                logging.error("Last 2 columns must be 0")
+                return False
+        return True
+
+    def prepare_test(self, shell):
+        # Follow the symlink
+        results = shell.Execute('readlink /proc/mounts')
+        if results[const.EXIT_CODE][0] != 0:
+            return False
+        return results[const.STDOUT][0] == 'self/mounts\n'
+
+    def get_path(self):
+        return "/proc/self/mounts"
diff --git a/api/proc/ProcQtaguidCtrlTest.py b/api/proc/ProcQtaguidCtrlTest.py
index 28f714f..102060b 100644
--- a/api/proc/ProcQtaguidCtrlTest.py
+++ b/api/proc/ProcQtaguidCtrlTest.py
@@ -14,41 +14,42 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
+from vts.utils.python.file import file_utils
 
 
 class ProcQtaguidCtrlTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/net/xt_qtaguid/ctrl provides information about tagged sockets.
-    '''
+    '''/proc/net/xt_qtaguid/ctrl provides information about tagged sockets.
 
-    start = 'content'
+    File content consists of possibly several lines of socket info followed by a
+    single line of events info, followed by a terminating newline.'''
 
-    t_EVENTS = literal_token(r'events')
-    t_TAG = literal_token(r'tag')
-    t_UID = literal_token(r'uid')
-    t_PID = literal_token(r'pid')
-    t_FCOUNT = literal_token(r'f_count')
-    t_LPAREN = literal_token(r'\(')
-    t_RPAREN = literal_token(r'\)')
-
-    p_lines = repeat_rule('line', zero_ok=True)
-    p_attrs = repeat_rule('attr')
-
-    def p_content(self, p):
-        'content : lines EVENTS COLON attrs NEWLINE'
-        p[0] = p[1:]
-
-    def p_line(self, p):
-        'line : STRING EQUALS NUMBER SPACE TAG EQUALS HEX_LITERAL SPACE \
-                LPAREN UID EQUALS NUMBER RPAREN SPACE PID EQUALS NUMBER SPACE \
-                FCOUNT EQUALS NUMBER NEWLINE'
-        p[0] = p[1:]
-
-    def p_attr(self, p):
-        'attr : SPACE STRING EQUALS NUMBER'
-        p[0] = [p[2], p[4]]
+    def parse_contents(self, contents):
+        result = []
+        lines = contents.split('\n')
+        if len(lines) == 0 or lines[-1] != '':
+            raise SyntaxError
+        for line in lines[:-2]:
+            parsed = self.parse_line(
+                "sock={:d} tag=0x{:x} (uid={:d}) pid={:d} f_count={:d}", line)
+            if any(map(lambda x: x < 0, parsed)):
+                raise SyntaxError("Negative numbers not allowed!")
+            result.append(parsed)
+        parsed = self.parse_line(
+            "events: sockets_tagged={:d} sockets_untagged={:d} counter_set_changes={:d} "
+            "delete_cmds={:d} iface_events={:d} match_calls={:d} match_calls_prepost={:d} "
+            "match_found_sk={:d} match_found_sk_in_ct={:d} match_found_no_sk_in_ct={:d} "
+            "match_no_sk={:d} match_no_sk_file={:d}", lines[-2])
+        if any(map(lambda x: x < 0, parsed)):
+            raise SyntaxError("Negative numbers not allowed!")
+        result.append(parsed)
+        return result
 
     def get_path(self):
         return "/proc/net/xt_qtaguid/ctrl"
+
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
diff --git a/api/proc/ProcRemoveUidRangeTest.py b/api/proc/ProcRemoveUidRangeTest.py
index 0cf345e..aeac742 100644
--- a/api/proc/ProcRemoveUidRangeTest.py
+++ b/api/proc/ProcRemoveUidRangeTest.py
@@ -14,41 +14,27 @@
 # limitations under the License.
 #
 
-import ProcShowUidStatTest
 from vts.runners.host import const
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.utils.python.file import file_utils
 
 
-class ProcRemoveUidRangeTest(ProcShowUidStatTest.ProcShowUidStatTest):
-    '''
-    /proc/uid_cputime/remove_uid_range can be written in order to remove uids
+class ProcRemoveUidRangeTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/uid_cputime/remove_uid_range can be written in order to remove uids
     from being shown when reading show_uid_stat.
 
     Format is '[start uid]-[end uid]'
 
     This is an Android specific file.
-
-    Attributes:
-        uid_remove: int, the uid that the test attempts to remove from show_uid_range
     '''
 
-    def prepare_test(self, shell):
-        # Remove the last uid
-        results = shell.Execute('cat %s' % self.get_path())
-        if results[const.EXIT_CODE][0] != 0:
-            return False
-        parsed = self.parse_contents(results[const.STDOUT][0])
-        self.uid_remove = parsed[-1][0]
+    def test_format(self):
+        return False
 
-        results = shell.Execute('echo "%d-%d" > /proc/uid_cputime/remove_uid_range' % \
-                (self.uid_remove, self.uid_remove))
-        if results[const.EXIT_CODE][0] != 0:
-            print "Failed to remove uid %d" % self.uid_remove
-            return False
-        return True
+    def get_permission_checker(self):
+        """Get write-only file permission checker.
+        """
+        return file_utils.IsWriteOnly
 
-    def result_correct(self, results):
-        for line in results:
-            if self.uid_remove == line[0]:
-                print line
-                return False
-        return True
+    def get_path(self):
+        return '/proc/uid_cputime/remove_uid_range'
diff --git a/api/proc/ProcShowUidStatTest.py b/api/proc/ProcShowUidStatTest.py
index d55985e..aa132c9 100644
--- a/api/proc/ProcShowUidStatTest.py
+++ b/api/proc/ProcShowUidStatTest.py
@@ -14,12 +14,11 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
 
 
 class ProcShowUidStatTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/uid_cputime/show_uid_stat provides the time a UID's processes spend
+    '''/proc/uid_cputime/show_uid_stat provides the time a UID's processes spend
     in user and kernel space.
 
     This is an Android specific file.
diff --git a/api/proc/ProcSimpleFileTests.py b/api/proc/ProcSimpleFileTests.py
index c3779bf..507f9be 100644
--- a/api/proc/ProcSimpleFileTests.py
+++ b/api/proc/ProcSimpleFileTests.py
@@ -14,19 +14,18 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+from vts.utils.python.file import file_utils
 
 
 class ProcKptrRestrictTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/sys/kernel/kptr_restrict determines whether kernel pointers are printed
+    '''/proc/sys/kernel/kptr_restrict determines whether kernel pointers are printed
     in proc files.
     '''
-    start = 'num'
 
-    def p_num(self, p):
-        'num : NUMBER NEWLINE'
-        p[0] = p[1]
+    def parse_contents(self, contents):
+        return self.parse_line("{:d}\n", contents)[0]
 
     def result_correct(self, result):
         return result >= 0 and result <= 4
@@ -34,17 +33,19 @@
     def get_path(self):
         return "/proc/sys/kernel/kptr_restrict"
 
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
+
 
 class ProcRandomizeVaSpaceTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/sys/kernel/randomize_va_space determines the address layout randomization
+    '''/proc/sys/kernel/randomize_va_space determines the address layout randomization
     policy for the system.
     '''
-    start = 'num'
 
-    def p_num(self, p):
-        'num : NUMBER NEWLINE'
-        p[0] = p[1]
+    def parse_contents(self, contents):
+        return self.parse_line("{:d}\n", contents)[0]
 
     def result_correct(self, result):
         return result >= 0 and result <= 2
@@ -52,16 +53,18 @@
     def get_path(self):
         return "/proc/sys/kernel/randomize_va_space"
 
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
+
 
 class ProcOverCommitMemoryTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/sys/vm/overcommit_memory determines the kernel virtual memory accounting mode.
     '''
-    /proc/sys/vm/overcommit_memory determines the kernel virtual memory accounting mode.
-    '''
-    start = 'num'
 
-    def p_num(self, p):
-        'num : NUMBER NEWLINE'
-        p[0] = p[1]
+    def parse_contents(self, contents):
+        return self.parse_line("{:d}\n", contents)[0]
 
     def result_correct(self, result):
         return result >= 0 and result <= 2
@@ -69,31 +72,35 @@
     def get_path(self):
         return "/proc/sys/vm/overcommit_memory"
 
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
+
 
 class ProcMmapMinAddrTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/sys/vm/mmap_min_addr specifies the minimum address that can be mmap'd.
     '''
-    /proc/sys/vm/mmap_min_addr specifies the minimum address that can be mmap'd.
-    '''
-    start = 'num'
 
-    def p_num(self, p):
-        'num : NUMBER NEWLINE'
-        p[0] = p[1]
+    def parse_contents(self, contents):
+        return self.parse_line("{:d}\n", contents)[0]
 
     def get_path(self):
         return "/proc/sys/vm/mmap_min_addr"
 
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
+
 
 class ProcMmapRndBitsTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/sys/vm/mmap_rnd_(compat_)bits specifies the amount of randomness in mmap'd
+    '''/proc/sys/vm/mmap_rnd_(compat_)bits specifies the amount of randomness in mmap'd
     addresses. Must be >= 8.
     '''
-    start = 'num'
 
-    def p_num(self, p):
-        'num : NUMBER NEWLINE'
-        p[0] = p[1]
+    def parse_contents(self, contents):
+        return self.parse_line("{:d}\n", contents)[0]
 
     def result_correct(self, result):
         return result >= 8
@@ -101,6 +108,11 @@
     def get_path(self):
         return "/proc/sys/vm/mmap_rnd_bits"
 
+    def get_permission_checker(self):
+        """Get r/w file permission checker.
+        """
+        return file_utils.IsReadWrite
+
 
 class ProcMmapRndCompatBitsTest(ProcMmapRndBitsTest):
     def get_path(self):
diff --git a/api/proc/ProcStatTest.py b/api/proc/ProcStatTest.py
index b22af0b..9d762b1 100644
--- a/api/proc/ProcStatTest.py
+++ b/api/proc/ProcStatTest.py
@@ -14,24 +14,63 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
 
 
 class ProcStatTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/stat provides kernel and system statistics.
-    '''
+    '''/proc/stat provides kernel and system statistics.'''
 
-    start = 'lines'
+    start = 'stat'
 
-    p_lines = repeat_rule('line')
+    t_CPU = literal_token(r'cpu[0-9]*')
+    t_INTR = literal_token(r'intr')
+    t_CTXT = literal_token(r'ctxt')
+    t_BTIME = literal_token(r'btime')
+    t_PROCESSES = literal_token(r'processes')
+    t_PROCS_RUNNING = literal_token(r'procs_running')
+    t_PROCS_BLOCKED = literal_token(r'procs_blocked')
+    t_SOFTIRQ = literal_token(r'softirq')
+
+    p_cpus = repeat_rule('cpu')
     p_numbers = repeat_rule('NUMBER')
 
     t_ignore = ' '
 
-    def p_line(self, p):
-        'line : STRING NUMBERs NEWLINE'
+    def p_stat(self, p):
+        'stat : cpus intr ctxt btime processes procs_running procs_blocked softirq'
+        p[0] = p[1:]
+
+    def p_cpu(self, p):
+        'cpu : CPU NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_intr(self, p):
+        'intr : INTR NUMBERs NEWLINE'
+        p[0] = p[1:]
+
+    def p_ctxt(self, p):
+        'ctxt : CTXT NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_btime(self, p):
+        'btime : BTIME NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_processes(self, p):
+        'processes : PROCESSES NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_procs_running(self, p):
+        'procs_running : PROCS_RUNNING NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_procs_blocked(self, p):
+        'procs_blocked : PROCS_BLOCKED NUMBER NEWLINE'
+        p[0] = p[1:]
+
+    def p_softirq(self, p):
+        'softirq : SOFTIRQ NUMBERs NEWLINE'
         p[0] = p[1:]
 
     def get_path(self):
diff --git a/api/proc/ProcVersionTest.py b/api/proc/ProcVersionTest.py
new file mode 100644
index 0000000..887235f
--- /dev/null
+++ b/api/proc/ProcVersionTest.py
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+
+
+class ProcVersionTest(KernelProcFileTestBase.KernelProcFileTestBase):
+    '''/proc/version displays the kernel version and build information.'''
+
+    def parse_contents(self, contents):
+        return self.parse_line("{} version {} ({}@{}) ({}) {}\n", contents)
+
+    def result_correct(self, parse_result):
+        if parse_result[0] != 'Linux' or len(parse_result[1].split('.')) != 3:
+            logging.error("Not a valid linux version!")
+            return False
+        return True
+
+    def get_path(self):
+        return "/proc/version"
diff --git a/api/proc/ProcVmallocInfoTest.py b/api/proc/ProcVmallocInfoTest.py
index a88bb45..c60fa93 100644
--- a/api/proc/ProcVmallocInfoTest.py
+++ b/api/proc/ProcVmallocInfoTest.py
@@ -14,37 +14,79 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
 
 
 class ProcVmallocInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/vmallocinfo provides info on vmalloc'd ranges.
-    '''
+    '''/proc/vmallocinfo provides info on vmalloc'd ranges.'''
 
     start = 'lines'
 
-    t_PLUS = literal_token(r'\+')
-    t_SLASH = literal_token(r'/')
-    t_STRING = r'[a-zA-Z\(\)_0-9\-@\.]+'
+    t_STRING = r'[^ ^\t^\n^-^=]+'
+
+    t_PAGES = literal_token('pages')
+    t_PHYS = literal_token('phys')
+    t_IOREMAP = literal_token('ioremap')
+    t_VMALLOC = literal_token('vmalloc')
+    t_VMAP = literal_token('vmap')
+    t_USER = literal_token('user')
+    t_VPAGES = literal_token('vpages')
+
     t_ignore = ' '
 
     p_lines = repeat_rule('line')
 
     def p_line(self, p):
-        '''line : addr_range NUMBER STRING NEWLINE
-                | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL STRING NEWLINE
-                | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL NEWLINE
-                | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL \
-                        STRING EQUALS NUMBER STRING NEWLINE
-                | addr_range NUMBER STRING PLUS HEX_LITERAL SLASH HEX_LITERAL \
-                        STRING EQUALS NUMBER STRING STRING NEWLINE'''
+        'line : addr_range NUMBER caller pages phys ioremap vmalloc vmap user vpages NEWLINE'
         p[0] = p[1:]
 
     def p_addr_range(self, p):
         'addr_range : HEX_LITERAL DASH HEX_LITERAL'
         p[0] = [p[1], p[3]]
 
+    def p_caller(self, p):
+        '''caller : STRING
+                  | empty'''
+        p[0] = p[1:]
+
+    def p_pages(self, p):
+        '''pages : PAGES EQUALS NUMBER
+                 | empty'''
+        if len(p) > 2:
+            p[0] = [p[1], p[3]]
+        else:
+            p[0] = []
+
+    def p_phys(self, p):
+        '''phys : PHYS EQUALS STRING
+                  | empty'''
+        p[0] = p[1:]
+
+    def p_ioremap(self, p):
+        '''ioremap : IOREMAP
+                   | empty'''
+        p[0] = p[1:]
+
+    def p_vmalloc(self, p):
+        '''vmalloc : VMALLOC
+                   | empty'''
+        p[0] = p[1:]
+
+    def p_vmap(self, p):
+        '''vmap : VMAP
+                | empty'''
+        p[0] = p[1:]
+
+    def p_user(self, p):
+        '''user : USER
+                | empty'''
+        p[0] = p[1:]
+
+    def p_vpages(self, p):
+        '''vpages : VPAGES
+                  | empty'''
+        p[0] = p[1:]
+
     def get_path(self):
         return "/proc/vmallocinfo"
diff --git a/api/proc/ProcZoneInfoTest.py b/api/proc/ProcZoneInfoTest.py
index da98a8e..867ad96 100644
--- a/api/proc/ProcZoneInfoTest.py
+++ b/api/proc/ProcZoneInfoTest.py
@@ -14,14 +14,12 @@
 # limitations under the License.
 #
 
-import KernelProcFileTestBase
-from KernelProcFileTestBase import repeat_rule, literal_token
+from vts.testcases.kernel.api.proc import KernelProcFileTestBase
+from vts.testcases.kernel.api.proc.KernelProcFileTestBase import repeat_rule, literal_token
 
 
 class ProcZoneInfoTest(KernelProcFileTestBase.KernelProcFileTestBase):
-    '''
-    /proc/zoneinfo displays information about memory zones.
-    '''
+    '''/proc/zoneinfo displays information about memory zones.'''
 
     t_APAGES = literal_token(r'pages')
     t_PAGESETS = literal_token(r'pagesets')
diff --git a/api/proc/required_kernel_configs.py b/api/proc/required_kernel_configs.py
deleted file mode 100644
index c99e6e7..0000000
--- a/api/proc/required_kernel_configs.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2017 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.
-#
-"""Required kernel configuration options for Treble.
-
-    TODO(jaeshin): Uncomment configs that are temporarily commented out
-    (# marlin) to ensure the testCheckConfigs test passes, once the marlin
-    kernel is updated.
-    TODO(jaeshin): Consolidate new config requirements with android-base.cfg
-
-    Kernel configuration requirements are specified in android-base.cfg
-
-    Key: config_name
-    Value: config_state
-        "y": enabled, represents both "y" and "m" options
-        "n": should not be set
-"""
-
-CONFIGS = {
-    # Loadable Kernel Modules
-    # "CONFIG_MODULES": "y", # marlin
-    # "CONFIG_MODULE_UNLOAD": "y", # marlin
-    # "CONFIG_MODVERSIONS": "y", # marlin
-    # "CONFIG_MODULE_SIG": "y", # marlin
-    # "CONFIG_MODULE_SIG_FORCE": "y", # marlin
-
-    # Device Tree Support
-    "CONFIG_OF": "y",
-    # "CONFIG_OF_*": "y",
-    # "CONFIG_PROC_DEVICETREE": "y", # for kernels prior to 3.15
-
-    # procfs
-    "CONFIG_PROC_FS": "y",
-    "CONFIG_PROC_SYSCTL": "y",
-    "CONFIG_PROC_PAGE_MONITOR": "y",
-    "CONFIG_PROC_PID_CPUSET": "y",
-    "CONFIG_IKCONFIG": "y",
-    "CONFIG_IKCONFIG_PROC": "y",
-
-    # sysfs
-    "CONFIG_SYSFS": "y",
-    "CONFIG_SYSFS_DEPRECATED": "n",
-
-    # debugfs
-    # "CONFIG_DEBUG_FS": "n", # marlin
-
-    # selinuxfs
-    # "CONFIG_SECURITY_SELINUX": "y", # duplicated below in android-base.cfg
-
-    # cgroups
-    # "CONFIG_CGROUPS": "y", # duplicated below in android-base.cfg
-    "CONFIG_CGROUP_DEBUG": "n",
-
-    # memory
-    # "CONFIG_MEMCG": "y", # marlin
-
-    # cpu
-    # "CONFIG_CGROUP_SCHED": "y", # duplicated below in android-base.cfg
-    # "CONFIG_RT_GROUP_SCHED": "y", # duplicated below in android-base.cfg
-    # "CONFIG_FAIR_GROUP_SCHED": "y",  # optional
-
-    # cpuacct
-    # "CONFIG_CGROUP_CPUACCT": "y", # duplicated below in android-base.cfg
-
-    # cpuset
-    "CONFIG_CPUSETS": "y",
-    # "CONFIG_PROC_PID_CPUSET": "y", # nice to have
-
-    # schedtune
-    "CONFIG_SCHED_TUNE": "y",
-
-    # pstore fs (PENDING confirmation from kernel team)
-    # "CONFIG_PSTORE": "y",
-    # "CONFIG_PSTORE_*": "y", # differs depending on your hardware, enable the ones present
-
-    # functionfs
-    # "CONFIG_USB_FUNCTIONFS": "y", # marlin
-    # "CONFIG_USB_*": "y", # possibly a few more
-
-    # android-base.cfg configs from
-    # https://android.googlesource.com/kernel/common/+/android-4.4/android/configs/android-base.cfg
-    "CONFIG_DEVKMEM": "n",
-    "CONFIG_DEVMEM": "n",
-    "CONFIG_INET_LRO": "n",
-    "CONFIG_OABI_COMPAT": "n",
-    "CONFIG_SYSVIPC": "n",
-    "CONFIG_ANDROID": "y",
-    "CONFIG_ANDROID_BINDER_IPC": "y",
-    "CONFIG_ANDROID_LOW_MEMORY_KILLER": "y",
-    "CONFIG_ARMV8_DEPRECATED": "y",
-    "CONFIG_ASHMEM": "y",
-    "CONFIG_AUDIT": "y",
-    "CONFIG_BLK_DEV_DM": "y",
-    "CONFIG_BLK_DEV_INITRD": "y",
-    "CONFIG_CGROUPS": "y",
-    "CONFIG_CGROUP_CPUACCT": "y",
-    "CONFIG_CGROUP_FREEZER": "y",
-    "CONFIG_CGROUP_SCHED": "y",
-    # "CONFIG_CP15_BARRIER_EMULATION": "y", # marlin
-    "CONFIG_DM_CRYPT": "y",
-    "CONFIG_DM_VERITY": "y",
-    "CONFIG_DM_VERITY_FEC": "y",
-    "CONFIG_EMBEDDED": "y",
-    "CONFIG_FB": "y",
-    "CONFIG_HARDENED_USERCOPY": "y",
-    "CONFIG_HIGH_RES_TIMERS": "y",
-    "CONFIG_INET6_AH": "y",
-    "CONFIG_INET6_ESP": "y",
-    "CONFIG_INET6_IPCOMP": "y",
-    "CONFIG_INET": "y",
-    "CONFIG_INET_DIAG_DESTROY": "y",
-    "CONFIG_INET_ESP": "y",
-    "CONFIG_INET_XFRM_MODE_TUNNEL": "y",
-    "CONFIG_IP6_NF_FILTER": "y",
-    "CONFIG_IP6_NF_IPTABLES": "y",
-    "CONFIG_IP6_NF_MANGLE": "y",
-    "CONFIG_IP6_NF_RAW": "y",
-    "CONFIG_IP6_NF_TARGET_REJECT": "y",
-    "CONFIG_IPV6": "y",
-    "CONFIG_IPV6_MIP6": "y",
-    "CONFIG_IPV6_MULTIPLE_TABLES": "y",
-    "CONFIG_IPV6_OPTIMISTIC_DAD": "y",
-    # "CONFIG_IPV6_PRIVACY": "y", # marlin
-    "CONFIG_IPV6_ROUTER_PREF": "y",
-    "CONFIG_IPV6_ROUTE_INFO": "y",
-    "CONFIG_IP_ADVANCED_ROUTER": "y",
-    # "CONFIG_IP_MULTICAST": "y", # marlin
-    "CONFIG_IP_MULTIPLE_TABLES": "y",
-    "CONFIG_IP_NF_ARPFILTER": "y",
-    "CONFIG_IP_NF_ARPTABLES": "y",
-    "CONFIG_IP_NF_ARP_MANGLE": "y",
-    "CONFIG_IP_NF_FILTER": "y",
-    "CONFIG_IP_NF_IPTABLES": "y",
-    "CONFIG_IP_NF_MANGLE": "y",
-    "CONFIG_IP_NF_MATCH_AH": "y",
-    "CONFIG_IP_NF_MATCH_ECN": "y",
-    "CONFIG_IP_NF_MATCH_TTL": "y",
-    "CONFIG_IP_NF_NAT": "y",
-    "CONFIG_IP_NF_RAW": "y",
-    "CONFIG_IP_NF_SECURITY": "y",
-    "CONFIG_IP_NF_TARGET_MASQUERADE": "y",
-    "CONFIG_IP_NF_TARGET_NETMAP": "y",
-    "CONFIG_IP_NF_TARGET_REDIRECT": "y",
-    "CONFIG_IP_NF_TARGET_REJECT": "y",
-    "CONFIG_NET": "y",
-    "CONFIG_NETDEVICES": "y",
-    "CONFIG_NETFILTER": "y",
-    # "CONFIG_NETFILTER_TPROXY": "y", # marlin
-    "CONFIG_NETFILTER_XT_MATCH_COMMENT": "y",
-    "CONFIG_NETFILTER_XT_MATCH_CONNLIMIT": "y",
-    "CONFIG_NETFILTER_XT_MATCH_CONNMARK": "y",
-    "CONFIG_NETFILTER_XT_MATCH_CONNTRACK": "y",
-    "CONFIG_NETFILTER_XT_MATCH_HASHLIMIT": "y",
-    "CONFIG_NETFILTER_XT_MATCH_HELPER": "y",
-    "CONFIG_NETFILTER_XT_MATCH_IPRANGE": "y",
-    "CONFIG_NETFILTER_XT_MATCH_LENGTH": "y",
-    "CONFIG_NETFILTER_XT_MATCH_LIMIT": "y",
-    "CONFIG_NETFILTER_XT_MATCH_MAC": "y",
-    "CONFIG_NETFILTER_XT_MATCH_MARK": "y",
-    "CONFIG_NETFILTER_XT_MATCH_PKTTYPE": "y",
-    "CONFIG_NETFILTER_XT_MATCH_POLICY": "y",
-    "CONFIG_NETFILTER_XT_MATCH_QTAGUID": "y",
-    "CONFIG_NETFILTER_XT_MATCH_QUOTA2": "y",
-    # "CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG": "y", # marlin
-    "CONFIG_NETFILTER_XT_MATCH_QUOTA": "y",
-    "CONFIG_NETFILTER_XT_MATCH_SOCKET": "y",
-    "CONFIG_NETFILTER_XT_MATCH_STATE": "y",
-    "CONFIG_NETFILTER_XT_MATCH_STATISTIC": "y",
-    "CONFIG_NETFILTER_XT_MATCH_STRING": "y",
-    "CONFIG_NETFILTER_XT_MATCH_TIME": "y",
-    "CONFIG_NETFILTER_XT_MATCH_U32": "y",
-    "CONFIG_NETFILTER_XT_TARGET_CLASSIFY": "y",
-    "CONFIG_NETFILTER_XT_TARGET_CONNMARK": "y",
-    "CONFIG_NETFILTER_XT_TARGET_CONNSECMARK": "y",
-    "CONFIG_NETFILTER_XT_TARGET_IDLETIMER": "y",
-    "CONFIG_NETFILTER_XT_TARGET_MARK": "y",
-    "CONFIG_NETFILTER_XT_TARGET_NFLOG": "y",
-    "CONFIG_NETFILTER_XT_TARGET_NFQUEUE": "y",
-    "CONFIG_NETFILTER_XT_TARGET_SECMARK": "y",
-    "CONFIG_NETFILTER_XT_TARGET_TCPMSS": "y",
-    "CONFIG_NETFILTER_XT_TARGET_TPROXY": "y",
-    "CONFIG_NETFILTER_XT_TARGET_TRACE": "y",
-    "CONFIG_NET_CLS_ACT": "y",
-    "CONFIG_NET_CLS_U32": "y",
-    "CONFIG_NET_EMATCH": "y",
-    "CONFIG_NET_EMATCH_U32": "y",
-    "CONFIG_NET_KEY": "y",
-    "CONFIG_NET_SCHED": "y",
-    "CONFIG_NET_SCH_HTB": "y",
-    "CONFIG_NF_CONNTRACK": "y",
-    "CONFIG_NF_CONNTRACK_AMANDA": "y",
-    "CONFIG_NF_CONNTRACK_EVENTS": "y",
-    "CONFIG_NF_CONNTRACK_FTP": "y",
-    "CONFIG_NF_CONNTRACK_H323": "y",
-    "CONFIG_NF_CONNTRACK_IPV4": "y",
-    "CONFIG_NF_CONNTRACK_IPV6": "y",
-    "CONFIG_NF_CONNTRACK_IRC": "y",
-    "CONFIG_NF_CONNTRACK_NETBIOS_NS": "y",
-    "CONFIG_NF_CONNTRACK_PPTP": "y",
-    "CONFIG_NF_CONNTRACK_SANE": "y",
-    "CONFIG_NF_CONNTRACK_SECMARK": "y",
-    "CONFIG_NF_CONNTRACK_TFTP": "y",
-    "CONFIG_NF_CT_NETLINK": "y",
-    "CONFIG_NF_CT_PROTO_DCCP": "y",
-    "CONFIG_NF_CT_PROTO_SCTP": "y",
-    "CONFIG_NF_CT_PROTO_UDPLITE": "y",
-    "CONFIG_NF_NAT": "y",
-    "CONFIG_NO_HZ": "y",
-    "CONFIG_PACKET": "y",
-    "CONFIG_PM_AUTOSLEEP": "y",
-    "CONFIG_PM_WAKELOCKS": "y",
-    "CONFIG_PPP": "y",
-    "CONFIG_PPPOLAC": "y",
-    "CONFIG_PPPOPNS": "y",
-    "CONFIG_PPP_BSDCOMP": "y",
-    "CONFIG_PPP_DEFLATE": "y",
-    "CONFIG_PPP_MPPE": "y",
-    "CONFIG_PREEMPT": "y",
-    "CONFIG_PROFILING": "y",
-    "CONFIG_QFMT_V2": "y",
-    "CONFIG_QUOTA": "y",
-    "CONFIG_QUOTA_NETLINK_INTERFACE": "y",
-    "CONFIG_QUOTA_TREE": "y",
-    "CONFIG_QUOTACTL": "y",
-    # "CONFIG_RANDOMIZE_BASE": "y", # marlin
-    "CONFIG_RTC_CLASS": "y",
-    "CONFIG_RT_GROUP_SCHED": "y",
-    "CONFIG_SECCOMP": "y",
-    "CONFIG_SECURITY": "y",
-    "CONFIG_SECURITY_NETWORK": "y",
-    "CONFIG_SECURITY_PERF_EVENTS_RESTRICT": "y",
-    "CONFIG_SECURITY_SELINUX": "y",
-    # "CONFIG_SETEND_EMULATION": "y", # marlin
-    "CONFIG_STAGING": "y",
-    "CONFIG_SWP_EMULATION": "y",
-    "CONFIG_SYNC": "y",
-    "CONFIG_TUN": "y",
-    # "CONFIG_UID_CPUTIME": "y", # marlin
-    "CONFIG_UNIX": "y",
-    "CONFIG_USB_GADGET": "y",
-    # "CONFIG_USB_CONFIGFS": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_FS": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_MTP": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_PTP": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_ACC": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_AUDIO_SRC": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_UEVENT": "y", # marlin
-    # "CONFIG_USB_CONFIGFS_F_MIDI": "y", # marlin
-    # "CONFIG_USB_OTG_WAKELOCK": "y", # marlin
-    "CONFIG_XFRM_USER": "y",
-}
diff --git a/api/qtaguid/Android.mk b/api/qtaguid/Android.mk
new file mode 100644
index 0000000..e4b56da
--- /dev/null
+++ b/api/qtaguid/Android.mk
@@ -0,0 +1,35 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := vts_test_binary_qtaguid_module
+LOCAL_SRC_FILES := SocketTagUserSpace.cpp
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libbase
+LOCAL_STATIC_LIBRARIES += libtestUtil
+LOCAL_C_INCLUDES += system/extras/tests/include \
+                    test/vts/testcases/system/qtaguid/sample
+LOCAL_CFLAGS += -fno-strict-aliasing
+
+include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsQtaguidTest
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/qtaguid
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/qtaguid/AndroidTest.xml b/api/qtaguid/AndroidTest.xml
new file mode 100644
index 0000000..cfc62a1
--- /dev/null
+++ b/api/qtaguid/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsQtaguidTest.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsQtaguidTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_test_binary_qtaguid_module/vts_test_binary_qtaguid_module" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_test_binary_qtaguid_module/vts_test_binary_qtaguid_module" />
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="10m" />
+    </test>
+</configuration>
diff --git a/api/qtaguid/SocketTagUserSpace.cpp b/api/qtaguid/SocketTagUserSpace.cpp
new file mode 100644
index 0000000..7c1a53a
--- /dev/null
+++ b/api/qtaguid/SocketTagUserSpace.cpp
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2017 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 requied 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.
+ *
+ */
+
+/*
+ * This socket tagging test is to ensure that the
+ * netfilter/xt_qtaguid kernel module somewhat behaves as expected
+ * with respect to tagging sockets.
+ */
+#define LOG_TAG "SocketTagUsrSpaceTest"
+#include "SocketTagUserSpace.h"
+#include <arpa/inet.h>
+#include <assert.h>
+#include <cutils/qtaguid.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <string>
+
+#include <fstream>
+
+#include <android-base/stringprintf.h>
+#include <gtest/gtest.h>
+#include <utils/Log.h>
+
+static const int kMaxCounterSet = 2;
+
+namespace android {
+
+/* A helper program to generate some traffic between two socket. */
+int server_download(SockInfo sock_server, SockInfo sock_client) {
+  struct sockaddr_in server, client;
+  server.sin_addr.s_addr = inet_addr("127.0.0.1");
+  server.sin_family = AF_INET;
+  server.sin_port = htons(8765);
+  if (bind(sock_server.fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
+    std::cerr << "bind failed" << std::endl;
+    return -1;
+  }
+  std::cout << "socket binded" << std::endl;
+  listen(sock_server.fd, 3);
+  std::cout << "waiting for connection...." << std::endl;
+  int sock_addr_length;
+  sock_addr_length = sizeof(struct sockaddr_in);
+  if (connect(sock_client.fd, (struct sockaddr *)&server, sizeof(server)), 0) {
+    return -1;
+  }
+  int new_socket;
+  new_socket = accept(sock_server.fd, (struct sockaddr *)&client,
+                      reinterpret_cast<socklen_t *>(&sock_addr_length));
+  if (new_socket < 0) {
+    return -1;
+  }
+  int packet_Count = 1024;
+  char byte_buffer[1024];
+  snprintf(byte_buffer, sizeof(byte_buffer), "%d", packet_Count);
+  send(sock_client.fd, "start", 5, 0);
+  if (recv(new_socket, byte_buffer, strlen(byte_buffer), 0) < 0) {
+    close(new_socket);
+    return -1;
+  }
+  memset(byte_buffer, 'x', 1023);
+  byte_buffer[1023] = '\0';
+  if (send(new_socket, byte_buffer, strlen(byte_buffer), 0) < 0) {
+    close(new_socket);
+    return -1;
+  }
+  EXPECT_GE(recv(sock_client.fd, byte_buffer, 1024, 0), 0);
+  close(new_socket);
+  return 0;
+}
+
+/* socket setup, initial the socket and try to validate the socket. */
+int SockInfo::setup(int tag) {
+  fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (fd < 0) {
+    std::cout << "socket creation failed: %s" << strerror(errno) << std::endl;
+    return -1;
+  }
+  if (qtaguid_tagSocket(fd, tag, getuid()) < 0) {
+    std::cout << "socket setup: failed to tag" << std::endl;
+    close(fd);
+    return -1;
+  }
+  if (!checkTag(tag, getuid())) {
+    std::cout << "socket setup: Unexpected results: tag not found" << std::endl;
+    close(fd);
+    return -1;
+  }
+  if (qtaguid_untagSocket(fd) < 0) {
+    std::cout << "socket setup: Unexpected results" << std::endl;
+    close(fd);
+    return -1;
+  }
+  return 0;
+}
+
+/* Check if the socket is properly tagged by read through the proc file.*/
+bool SockInfo::checkTag(uint64_t acct_tag, uid_t uid) {
+  int res;
+  uint64_t k_tag;
+  uint32_t k_uid;
+  long dummy_count;
+  pid_t dummy_pid;
+
+  std::ifstream fctrl("/proc/net/xt_qtaguid/ctrl", std::fstream::in);
+  if (!fctrl.is_open()) {
+    std::cout << "qtaguid ctrl open failed!" << std::endl;
+  }
+
+  uint64_t full_tag = (acct_tag << 32) | uid;
+  std::string buff =
+      android::base::StringPrintf(" tag=0x%" PRIx64 " (uid=%u)", full_tag, uid);
+
+  std::cout << "looking for " << buff.c_str() << std::endl;
+  std::string ctrl_data;
+  std::size_t pos = std::string::npos;
+  while (std::getline(fctrl, ctrl_data)) {
+    pos = ctrl_data.find(buff);
+    if (pos != std::string::npos) break;
+  }
+  return pos != std::string::npos;
+}
+
+/*
+ * Check if the socket traffic statistics is properly recorded by reading the
+ * corresponding proc file.
+ */
+bool SockInfo::checkStats(uint64_t acct_tag, uid_t uid, int counterSet,
+                          uint32_t *stats_result) {
+  FILE *stats_fd;
+  ssize_t read_size;
+  size_t line_size;
+  uint64_t kTag = (uint64_t)acct_tag << 32;
+  std::ifstream fstats("/proc/net/xt_qtaguid/stats", std::fstream::in);
+  if (!fstats.is_open()) {
+    std::cout << "qtaguid ctrl open failed!" << std::endl;
+  }
+  std::string buff =
+      android::base::StringPrintf("0x%" PRIx64 " %u %d", kTag, uid, counterSet);
+  std::string stats_data;
+  std::size_t pos = std::string::npos;
+  std::cout << "looking for data " << buff << std::endl;
+  while (std::getline(fstats, stats_data)) {
+    pos = stats_data.find(buff);
+    if (pos != std::string::npos) {
+      std::cout << "match_data: " << stats_data << std::endl;
+      std::string match_data = stats_data.substr(pos);
+      sscanf(match_data.c_str(), "0x%" PRIx64 " %u %d %d %d", &kTag, &uid,
+             &counterSet, stats_result, stats_result + 1);
+      return pos != std::string::npos;
+    }
+  }
+  return pos != std::string::npos;
+}
+
+class SocketTagUsrSpaceTest : public ::testing::Test {
+ protected:
+  uint32_t stats_result_[2];
+  SockInfo sock_0;
+  SockInfo sock_1;
+  uid_t fake_uid;
+  uid_t fake_uid2;
+  uid_t inet_uid;
+  uid_t my_uid;
+  pid_t my_pid;
+  int valid_tag1;
+  int valid_tag2;
+  uint64_t max_uint_tag;
+
+  virtual void SetUp() {
+    my_uid = getuid();
+    my_pid = getpid();
+    srand48(my_pid * my_uid);
+    // Adjust fake UIDs and tags so that multiple instances can run
+    // in parallel.
+    fake_uid = rand() & 0x7FFFFFFF;
+    fake_uid2 = rand() & 0x7FFFFFFF;
+    inet_uid = 1024;
+    valid_tag1 = (my_pid << 12) | (rand());
+    valid_tag2 = (my_pid << 12) | (rand());
+    std::cout << "* start: pid=" << my_pid << " uid=" << my_uid
+              << " uid1=0x" << std::hex << fake_uid << " uid2=0x"
+              << fake_uid2 << " inetuid=0x" << inet_uid << "tag1=0x%"
+              << valid_tag1 << " tag2=0x%" << valid_tag2 << std::endl;
+    max_uint_tag = 0xffffffff00000000llu;
+    max_uint_tag = 1llu << 63 | (((uint64_t)my_pid << 48) ^ max_uint_tag);
+    // Check the node /dev/xt_qtaguid exist before start.
+    struct stat nodeStat;
+    EXPECT_GE(stat("/dev/xt_qtaguid", &nodeStat), 0)
+        << "fail to check /dev/xt_qtaguid";
+    // We want to clean up any previous faulty test runs.
+    EXPECT_GE(qtaguid_deleteTagData(0, fake_uid), 0)
+        << "Failed to delete fake_uid";
+    EXPECT_GE(qtaguid_deleteTagData(0, fake_uid2), 0)
+        << "Failed to delete fake_uid2";
+    EXPECT_GE(qtaguid_deleteTagData(0, my_uid), 0) << "Failed to delete my_uid";
+    EXPECT_GE(qtaguid_deleteTagData(0, inet_uid), 0)
+        << "Failed to delete inet_uid";
+    EXPECT_GE(qtaguid_setPacifier(0), 0) << "Turn off pacifier fail";
+    ASSERT_FALSE(sock_0.setup(valid_tag1)) << "socket0 setup failed";
+    ASSERT_FALSE(sock_1.setup(valid_tag1)) << "socket1 setup failed";
+  }
+
+  virtual void TearDown() {
+    if (sock_0.fd >= 0) {
+      close(sock_0.fd);
+    }
+    if (sock_1.fd >= 0) {
+      close(sock_1.fd);
+    }
+  }
+};
+
+/* Tag to a invalid socket fd, should fail */
+TEST_F(SocketTagUsrSpaceTest, invalidSockfdFail) {
+  EXPECT_LT(qtaguid_tagSocket(-1, valid_tag1, my_uid), 0)
+      << "Invalid socketfd case 1, should fail.";
+}
+
+/* Check the stats of a invalid socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, CheckStatsInvalidSocketFail) {
+  memset(stats_result_, 0, 2);
+  EXPECT_FALSE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+      << "No stats should be here";
+}
+
+/* Untag invalid socket fd, should fail */
+TEST_F(SocketTagUsrSpaceTest, UntagInvalidSocketFail) {
+  EXPECT_LT(qtaguid_untagSocket(-1), 0) << "invalid socket fd, should fail";
+  EXPECT_LT(qtaguid_untagSocket(sock_0.fd), 0)
+      << "no tags on sock0, should fail";
+}
+
+/*
+ * Set the counter to a number larger then max counter avalaible
+ * should fail
+ */
+TEST_F(SocketTagUsrSpaceTest, CounterSetNumExceedFail) {
+  int wrongCounterNum = kMaxCounterSet + 1;
+  EXPECT_LT(qtaguid_setCounterSet(wrongCounterNum, my_uid), 0)
+      << "Invalid counter set number, should fail.";
+}
+
+/* Tag without valid uid, should be tagged with my_uid */
+TEST_F(SocketTagUsrSpaceTest, NoUidTag) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, 0), 0)
+      << "tag failed without uid";
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+}
+
+/*
+ * Tag without tag and uid number, should be tagged with tag 0 and
+ * my_uid
+ */
+TEST_F(SocketTagUsrSpaceTest, NoTagNoUid) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, 0, 0), 0)
+      << "no tag and uid infomation";
+  ASSERT_TRUE(sock_0.checkTag(0, my_uid)) << "Tag not found";
+}
+
+/* Untag from a tagged socket */
+TEST_F(SocketTagUsrSpaceTest, ValidUntag) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found";
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag should be removed";
+}
+
+/* Tag a socket for the first time */
+TEST_F(SocketTagUsrSpaceTest, ValidFirsttag) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+/* ReTag a already tagged socket with the same tag and uid */
+TEST_F(SocketTagUsrSpaceTest, ValidReTag) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid)) << "Tag not found.";
+}
+
+/*
+ * Retag a already tagged socket with the same uid but different tag
+ * Should keep the second one and untag the original one
+ */
+TEST_F(SocketTagUsrSpaceTest, ValidReTagWithAcctTagChange) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+  EXPECT_FALSE(sock_0.checkTag(valid_tag2, fake_uid))
+      << "Tag should not be here";
+}
+
+/*
+ * Retag a already tagged socket with different uid and different tag.
+ * Should keep both
+ */
+TEST_F(SocketTagUsrSpaceTest, ReTagWithUidChange) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid2), 0);
+}
+
+/*
+ * Retag a already tagged socket with different uid but the same tag.
+ * The original one should be replaced by the new one.
+ */
+TEST_F(SocketTagUsrSpaceTest, ReTagWithUidChange2) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag2, fake_uid2), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag2, fake_uid2)) << "Tag not found.";
+  EXPECT_FALSE(sock_0.checkTag(valid_tag2, fake_uid))
+      << "Tag should not be here";
+}
+
+/* Tag two sockets with two uids and two tags. */
+TEST_F(SocketTagUsrSpaceTest, TagAnotherSocket) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, max_uint_tag, my_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_FALSE(sock_0.checkTag(max_uint_tag, fake_uid))
+      << "Tag should not be there";
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+  EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+  EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+      << "Tag should not be there";
+}
+
+/* Tag two sockets with the same uid but different acct_tags. */
+TEST_F(SocketTagUsrSpaceTest, SameUidTwoSocket) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag2, my_uid), 0);
+  EXPECT_TRUE(sock_1.checkTag(valid_tag2, my_uid)) << "Tag not found.";
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, my_uid)) << "Tag not found.";
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid))
+
+      << "Tag should not be there";
+  EXPECT_TRUE(sock_1.checkTag(valid_tag2, my_uid)) << "Tag not found";
+  EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+  EXPECT_FALSE(sock_1.checkTag(valid_tag2, my_uid))
+      << "Tag should not be there";
+}
+
+/* Tag two sockets with the same acct_tag but different uids */
+TEST_F(SocketTagUsrSpaceTest, SameTagTwoSocket) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid)) << "Tag not found.";
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid2)) << "Tag not found.";
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_FALSE(sock_0.checkTag(valid_tag1, fake_uid))
+      << "Tag should not be there";
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+  EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+  EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+      << "Tag should not be there";
+}
+
+/* Tag a closed socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, TagInvalidSocketFail) {
+  close(sock_0.fd);
+  EXPECT_LT(qtaguid_tagSocket(sock_0.fd, valid_tag1, my_uid), 0);
+  EXPECT_FALSE(sock_0.checkTag(valid_tag1, my_uid))
+      << "Tag should not be there";
+}
+
+/* untag from a closed socket, should fail. */
+TEST_F(SocketTagUsrSpaceTest, UntagClosedSocketFail) {
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, my_uid), 0);
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, my_uid));
+  close(sock_1.fd);
+  EXPECT_LT(qtaguid_untagSocket(sock_1.fd), 0)
+      << "no tag attached, should fail";
+}
+
+/*
+ * set the pacifier ON and try to modify the tags, expect no change to the
+ * ctrl and stats file.
+ */
+TEST_F(SocketTagUsrSpaceTest, PacifierFunctionTest) {
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, max_uint_tag, my_uid), 0);
+  EXPECT_GE(qtaguid_setPacifier(1), 0);
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+  EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+      << "Tag should not be there.";
+  EXPECT_GE(qtaguid_setPacifier(0), 0);
+  EXPECT_FALSE(sock_1.checkTag(valid_tag1, fake_uid2))
+      << "Tag should not be there.";
+  EXPECT_TRUE(sock_0.checkTag(max_uint_tag, my_uid)) << "tag not found";
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, fake_uid2), 0);
+  EXPECT_FALSE(sock_0.checkTag(max_uint_tag, fake_uid))
+      << "Tag should not be there";
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, fake_uid2)) << "Tag not found";
+}
+
+/*
+ * try to connect with google.com in order to generate some
+ * tranffic through the socket, the traffic statistics should
+ * be stored in the stats file and will be returned.
+ */
+TEST_F(SocketTagUsrSpaceTest, dataTransmitTest) {
+  memset(stats_result_, 0, 2);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, inet_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, inet_uid)) << "tag not found";
+  EXPECT_GE(server_download(sock_0, sock_1), 0);
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  close(sock_0.fd);
+  EXPECT_TRUE(sock_0.checkStats(valid_tag1, inet_uid, 0, stats_result_))
+      << "failed to retreive data";
+  std::cout << "the receive packet count is " << stats_result_[1]
+            << ", the byte count is " << stats_result_[0] << std::endl;
+  EXPECT_GT(*stats_result_, (uint32_t)0) << "no stats found for this socket";
+  EXPECT_GT(*(stats_result_ + 1), (uint32_t)0)
+      << "no stats stored for this socket";
+}
+
+/* Generate some traffic first and then delete the
+ * tag and uid from stats. All the stats related should
+ * be deleted. checkStats() should return false.
+ */
+TEST_F(SocketTagUsrSpaceTest, dataStatsDeleteTest) {
+  memset(stats_result_, 0, 2);
+  EXPECT_GE(qtaguid_tagSocket(sock_0.fd, valid_tag1, fake_uid), 0);
+  EXPECT_TRUE(sock_0.checkTag(valid_tag1, fake_uid)) << "tag not found";
+  EXPECT_GE(server_download(sock_0, sock_1), 0);
+  EXPECT_GE(qtaguid_untagSocket(sock_0.fd), 0);
+  EXPECT_TRUE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+      << "failed to retreive data";
+  std::cout << "the receive packet count is " << stats_result_[1]
+            << ", the byte count is " << stats_result_[0] << std::endl;
+  EXPECT_GT(*stats_result_, (uint32_t)0) << "no stats found for this socket";
+  EXPECT_GT(*(stats_result_ + 1), (uint32_t)0)
+      << "no stats stored for this socket";
+  EXPECT_GE(qtaguid_deleteTagData(0, fake_uid), 0)
+      << "Failed to delete fake_uid";
+  EXPECT_FALSE(sock_0.checkStats(valid_tag1, fake_uid, 0, stats_result_))
+      << "NO DATA should be stored";
+}
+
+/*
+ * try to store the traffic stats in the secound counter
+ * insdead of the first. All the stats should be stored
+ * in the secound counter.
+ */
+TEST_F(SocketTagUsrSpaceTest, CounterSetTest) {
+  memset(stats_result_, 0, 2);
+  EXPECT_GE(qtaguid_tagSocket(sock_1.fd, valid_tag1, inet_uid), 0);
+  EXPECT_GE(qtaguid_setCounterSet(1, inet_uid), 0);
+  EXPECT_TRUE(sock_1.checkTag(valid_tag1, inet_uid)) << "tag not found";
+  EXPECT_GE(server_download(sock_0, sock_1), 0);
+  EXPECT_GE(qtaguid_untagSocket(sock_1.fd), 0);
+  close(sock_1.fd);
+  EXPECT_TRUE(sock_1.checkStats(valid_tag1, inet_uid, 1, stats_result_))
+      << "failed to retreive data";
+  uint32_t packet_count = 1;
+  uint32_t total_byte = 1024;
+  std::cout << "the receive packet count is " << stats_result_[1]
+            << ", the byte count is " << stats_result_[0] << std::endl;
+  EXPECT_GT(*stats_result_, total_byte) << "no stats found for this socket";
+  EXPECT_GT(*(stats_result_ + 1), packet_count)
+      << "wrong stats stored for this socket";
+  uint32_t stats_foreground[2] = {0, 0};
+  EXPECT_TRUE(sock_0.checkStats(valid_tag1, inet_uid, 0, stats_foreground))
+      << "fail to retrieve data";
+  EXPECT_LE(*stats_foreground, (uint32_t)0) << "stats data is not zero";
+}
+}  // namespace android
diff --git a/api/qtaguid/SocketTagUserSpace.h b/api/qtaguid/SocketTagUserSpace.h
new file mode 100644
index 0000000..0bed2f7
--- /dev/null
+++ b/api/qtaguid/SocketTagUserSpace.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 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.
+ *
+ */
+
+#ifndef _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
+#define _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+namespace android {
+
+// Class created to store socket file description and setup socket
+class SockInfo {
+ public:
+  SockInfo() : fd(-1) {}
+  // set up the socket and verify it by trying to tag it
+  int setup(int tag);
+  // helper function check if the socket is tagged correctly
+  bool checkTag(uint64_t acct_tag, uid_t uid);
+  // helper function check if the socket traffic is properly recorded.
+  bool checkStats(uint64_t acct_tag, uid_t uid, int counterSet,
+                  uint32_t *stats_result);
+  // socket file description
+  int fd;
+};
+
+}  // namespace android
+
+#endif  // _VTS_SYSTEM_QTAGUID_SOCKET_TAG_USER_SPACE_
diff --git a/api/selinux/Android.mk b/api/selinux/Android.mk
new file mode 100644
index 0000000..244af93
--- /dev/null
+++ b/api/selinux/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelSelinuxFileApi
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/selinux
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/selinux/AndroidTest.xml b/api/selinux/AndroidTest.xml
new file mode 100644
index 0000000..1e4e018
--- /dev/null
+++ b/api/selinux/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelSelinuxFileApiTest test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HostDrivenTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelSelinuxFileApi" />
+        <option name="test-case-path" value="vts/testcases/kernel/api/selinux/VtsKernelSelinuxFileApiTest" />
+    </test>
+</configuration>
diff --git a/api/selinux/KernelSelinuxFileTestBase.py b/api/selinux/KernelSelinuxFileTestBase.py
new file mode 100644
index 0000000..d48e007
--- /dev/null
+++ b/api/selinux/KernelSelinuxFileTestBase.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+from abc import ABCMeta
+from abc import abstractmethod
+
+from vts.utils.python.file import file_utils
+
+class KernelSelinuxFileTestBase(object):
+    """Abstract test for the formatting of a selinux file.
+
+    Individual files can inherit from this class and define the correct path,
+    file content, and permissions.
+    """
+    __metaclass__ = ABCMeta
+
+    @abstractmethod
+    def get_path(self):
+        """Return the full path of this selinux file."""
+        pass
+
+    def result_correct(self, file_contents):
+        """Return True if the file contents are correct.
+
+        Subclasses define the requirements for the selinux file and validate
+        that the contents of a file are correct.
+
+        Args:
+            file_contents: String, the contents of an selinux file
+
+        Returns:
+            True if the contents are correct, False otherwise.
+        """
+        return True
+
+    def get_permission_checker(self):
+        """Gets the function handle to use for validating file permissions.
+
+        Return the function that will check if the permissions are correct.
+        By default, return the IsReadOnly function from file_utils.
+
+        Returns:
+            function which takes one argument (the unix file permission bits
+            in octal format) and returns True if the permissions are correct,
+            False otherwise.
+        """
+        return file_utils.IsReadOnly
diff --git a/api/selinux/SelinuxCheckReqProtTest.py b/api/selinux/SelinuxCheckReqProtTest.py
new file mode 100644
index 0000000..5d091a5
--- /dev/null
+++ b/api/selinux/SelinuxCheckReqProtTest.py
@@ -0,0 +1,42 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxCheckReqProt(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+    """Validate /sys/fs/selinux/checkreqprot content and permissions.
+
+    The contents are binary 0/1 and the file should be read/write.
+    """
+
+    def get_path(self):
+        return "/sys/fs/selinux/checkreqprot"
+
+    def result_correct(self, file_content):
+        """Return True if the file contents are simply 0/1.
+
+        Args:
+            file_contents: String, the contents of the checkreqprot file
+
+        Returns:
+            True if the contents are 0/1, False otherwise.
+        """
+        return file_content == "0" or file_content == "1"
+
+    def get_permission_checker(self):
+        """Gets the function handle to validate r/w file permissions."""
+        return file_utils.IsReadWrite
diff --git a/api/selinux/SelinuxNullTest.py b/api/selinux/SelinuxNullTest.py
new file mode 100644
index 0000000..611e492
--- /dev/null
+++ b/api/selinux/SelinuxNullTest.py
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxNull(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+    """Validate /sys/fs/selinux/null permissions.
+
+    The file should be read/write; there are no tests for content format.
+    """
+
+    def get_path(self):
+        return "/sys/fs/selinux/null"
+
+    def get_permission_checker(self):
+        """Gets the function handle to validate r/w file permissions."""
+        return file_utils.IsReadWrite
diff --git a/api/selinux/SelinuxPolicyTest.py b/api/selinux/SelinuxPolicyTest.py
new file mode 100644
index 0000000..9c79336
--- /dev/null
+++ b/api/selinux/SelinuxPolicyTest.py
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2017 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.
+#
+from vts.testcases.kernel.api.selinux import KernelSelinuxFileTestBase
+from vts.utils.python.file import file_utils
+
+
+class SelinuxPolicy(KernelSelinuxFileTestBase.KernelSelinuxFileTestBase):
+    """Validate /sys/fs/selinux/policy permissions.
+
+    The file permission should be read-only. No content testing at this time.
+    """
+
+    def get_path(self):
+        return "/sys/fs/selinux/policy"
diff --git a/api/selinux/VtsKernelSelinuxFileApiTest.py b/api/selinux/VtsKernelSelinuxFileApiTest.py
new file mode 100644
index 0000000..d35e33b
--- /dev/null
+++ b/api/selinux/VtsKernelSelinuxFileApiTest.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.testcases.kernel.api.selinux import SelinuxCheckReqProtTest
+from vts.testcases.kernel.api.selinux import SelinuxPolicyTest
+from vts.testcases.kernel.api.selinux import SelinuxNullTest
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+TEST_OBJECTS = {
+    SelinuxCheckReqProtTest.SelinuxCheckReqProt(),
+    SelinuxPolicyTest.SelinuxPolicy(),
+    SelinuxNullTest.SelinuxNull()
+}
+
+class VtsKernelSelinuxFileApiTest(base_test.BaseTestClass):
+    """Test cases which check content of selinuxfs files.
+    """
+
+    def setUpClass(self):
+        self.dut = self.registerController(android_device)[0]
+        self.dut.shell.InvokeTerminal(
+            "KernelSelinuxFileApiTest")  # creates a remote shell instance.
+        self.shell = self.dut.shell.KernelSelinuxFileApiTest
+
+    def runSelinuxFileTest(self, test_object):
+        """Reads the file and checks that its content and permissions are valid.
+
+        Args:
+            test_object: inherits KernelSelinuxFileTestBase, contains the test functions
+        """
+        logging.info("Testing existence of %s" % (test_object.get_path()))
+
+        asserts.assertTrue(
+            file_utils.Exists(test_object.get_path(), self.shell),
+            "%s: File does not exist." % test_object.get_path())
+
+        logging.info("Testing permissions of %s" % (test_object.get_path()))
+        try:
+            permissions = file_utils.GetPermission(
+                test_object.get_path(), self.shell)
+            asserts.assertTrue(test_object.get_permission_checker()(permissions),
+                               "%s: File has invalid permissions (%s)" %
+                               (test_object.get_path(), permissions))
+        except (ValueError, IOError) as e:
+            asserts.fail("Failed to assert permissions: %s" % str(e))
+
+        logging.info("Testing format of %s" % (test_object.get_path()))
+        file_content = file_utils.ReadFileContent(
+            test_object.get_path(), self.shell)
+        asserts.assertTrue(
+            test_object.result_correct(file_content), "Results not valid!")
+
+    def generateProcFileTests(self):
+        """Run all selinux file tests."""
+        self.runGeneratedTests(test_func=self.runSelinuxFileTest,
+                settings=TEST_OBJECTS,
+                name_func=lambda test_obj: "test" + test_obj.__class__.__name__)
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/api/selinux/__init__.py b/api/selinux/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/selinux/__init__.py
diff --git a/api/sysfs/Android.mk b/api/sysfs/Android.mk
new file mode 100644
index 0000000..78b6f0c
--- /dev/null
+++ b/api/sysfs/Android.mk
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelApiSysfsTest
+VTS_CONFIG_SRC_DIR := testcases/kernel/api/sysfs
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/sysfs/AndroidTest.xml b/api/sysfs/AndroidTest.xml
new file mode 100644
index 0000000..e398c25
--- /dev/null
+++ b/api/sysfs/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelApiTest test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HostDrivenTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelApiSysfs" />
+        <option name="test-case-path" value="vts/testcases/kernel/api/sysfs/KernelApiSysfsTest" />
+    </test>
+</configuration>
diff --git a/api/sysfs/KernelApiSysfsTest.py b/api/sysfs/KernelApiSysfsTest.py
new file mode 100644
index 0000000..78ed074
--- /dev/null
+++ b/api/sysfs/KernelApiSysfsTest.py
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import logging
+import re
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+
+class KernelApiSysfsTest(base_test.BaseTestClass):
+    '''Test cases which check sysfs files.'''
+
+    def setUpClass(self):
+        self.dut = self.registerController(android_device)[0]
+        self.dut.shell.InvokeTerminal(
+            'default')  # creates a remote shell instance.
+        self.shell = self.dut.shell.default
+
+    def ConvertToInteger(self, text):
+        '''Check whether a given text is interger.
+
+        Args:
+            text: object, usually a string representing the content of a file
+
+        Returns:
+            bool, True if is integer
+        '''
+        try:
+            return int(text)
+        except ValueError as e:
+            logging.exception(e)
+            asserts.fail('Content "%s" is not integer' % text)
+
+    def MatchRegex(self, regex, string):
+        '''Check whether a string completely matches a given regex.
+
+        Assertions will fail if given string is not a complete match.
+
+        Args:
+            regex: string, regex pattern to match
+            string: string, given string for matching
+        '''
+        pattern = re.compile(regex)
+        match = pattern.match(string)
+        message = 'String "%s" is not a complete match of regex "%s".' % (
+            string, regex)
+        asserts.assertTrue(match is not None, message)
+        asserts.assertEqual(match.start(), 0, message)
+        asserts.assertEqual(match.end(), len(string), message)
+
+    def IsReadOnly(self, path):
+        '''Check whether a given path is read only.
+
+        Assertion will fail if given path does not exist or is not read only.
+        '''
+        permission = ''
+        try:
+            permission = file_utils.GetPermission(path, self.shell)
+        except IOError as e:
+            logging.exception(e)
+            asserts.fail('Path "%s" does not exist or has invalid '
+                         'permission bits' % path)
+
+        try:
+            asserts.assertTrue(
+                file_utils.IsReadOnly(permission),
+                'path %s is not read only' % path)
+        except IOError as e:
+            logging.exception(e)
+            asserts.fail('Got invalid permission bits "%s" for path "%s"' %
+                         (permission, path))
+
+    def testCpuOnlineFormat(self):
+        '''Check the format of cpu online file.
+
+        Confirm /sys/devices/system/cpu/online exists and is read-only.
+        Parse contents to ensure it is a comma-separated series of ranges
+        (%d-%d) and/or integers.
+        '''
+        filepath = '/sys/devices/system/cpu/online'
+        self.IsReadOnly(filepath)
+        content = file_utils.ReadFileContent(filepath, self.shell)
+        regex = '(\d+(-\d+)?)(,\d+(-\d+)?)*'
+        if content.endswith('\n'):
+            content = content[:-1]
+        self.MatchRegex(regex, content)
+
+    def testLastResumeReason(self):
+        '''Check /sys/kernel/wakeup_reasons/last_resume_reason.'''
+        filepath = '/sys/kernel/wakeup_reasons/last_resume_reason'
+        self.IsReadOnly(filepath)
+
+    def testKernelMax(self):
+        '''Check the value of /sys/devices/system/cpu/kernel_max.'''
+        filepath = '/sys/devices/system/cpu/kernel_max'
+        self.IsReadOnly(filepath)
+        content = file_utils.ReadFileContent(filepath, self.shell)
+        self.ConvertToInteger(content)
+
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/api/sysfs/__init__.py b/api/sysfs/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/api/sysfs/__init__.py
diff --git a/api/tun/Android.bp b/api/tun/Android.bp
new file mode 100644
index 0000000..f065de2
--- /dev/null
+++ b/api/tun/Android.bp
@@ -0,0 +1,24 @@
+// Copyright (C) 2017 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.
+
+cc_test {
+    name: "vts_kernel_tun_test",
+    srcs: [
+        "vts_kernel_tun_test.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+    ],
+}
+
diff --git a/api/tun/Android.mk b/api/tun/Android.mk
new file mode 100644
index 0000000..09fc0b1
--- /dev/null
+++ b/api/tun/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelTunTest
+include test/vts/tools/build/Android.host_config.mk
diff --git a/api/tun/AndroidTest.xml b/api/tun/AndroidTest.xml
new file mode 100644
index 0000000..87e20c8
--- /dev/null
+++ b/api/tun/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS VtsKernelTunTest.">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="abort-on-push-failure" value="false"/>
+        <option name="push-group" value="HostDrivenTest.push"/>
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer"/>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelTunTest"/>
+        <option name="binary-test-source" value="_32bit::DATA/nativetest/vts_kernel_tun_test/vts_kernel_tun_test" />
+        <option name="binary-test-source" value="_64bit::DATA/nativetest64/vts_kernel_tun_test/vts_kernel_tun_test" />
+        <option name="binary-test-type" value="gtest"/>
+        <option name="test-timeout" value="10m"/>
+    </test>
+</configuration>
diff --git a/api/tun/vts_kernel_tun_test.cpp b/api/tun/vts_kernel_tun_test.cpp
new file mode 100644
index 0000000..701a19d
--- /dev/null
+++ b/api/tun/vts_kernel_tun_test.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include <iostream>
+#include <string>
+
+#include <fcntl.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+
+using std::cout;
+using std::endl;
+using std::string;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+
+static const short kTunModes[] = {
+  IFF_TUN,
+  IFF_TAP,
+};
+
+class VtsKernelTunTest : public ::testing::TestWithParam<short> {
+ public:
+  virtual void SetUp() override {
+    tun_device_ = "/dev/tun";
+    uint32_t num = arc4random_uniform(1000);
+    ifr_name_ = StringPrintf("tun%d", num);
+  }
+
+  // Used to initialize tun device.
+  int TunInit(short flags);
+
+  string tun_device_;
+  string ifr_name_;
+  unique_fd fd_;
+};
+
+int VtsKernelTunTest::TunInit(short mode) {
+  struct ifreq ifr = {
+    .ifr_flags = mode,
+  };
+  strncpy(ifr.ifr_name, ifr_name_.c_str(), IFNAMSIZ);
+  int fd = open(tun_device_.c_str(), O_RDWR | O_NONBLOCK);
+  if (fd < 0) {
+    return -1;
+  }
+  if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
+    close(fd);
+    return -1;
+  }
+  return fd;
+}
+
+// Test opening and closing of a tun interface.
+TEST_P(VtsKernelTunTest, OpenAndClose) {
+  fd_ = unique_fd(TunInit(GetParam()));
+  ASSERT_TRUE(fd_ >= 0);
+}
+
+// Test basic read functionality of a tuen interface.
+TEST_P(VtsKernelTunTest, BasicRead) {
+  fd_ = unique_fd(TunInit(GetParam()));
+  ASSERT_TRUE(fd_ >= 0);
+
+  uint8_t test_output;
+  // Expect no packets available on this interface.
+  ASSERT_TRUE(read(fd_, &test_output, 1) < 0);
+}
+
+INSTANTIATE_TEST_CASE_P(Basic, VtsKernelTunTest,
+                        ::testing::ValuesIn(kTunModes));
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/config/Android.mk b/config/Android.mk
new file mode 100644
index 0000000..f9c3bbb
--- /dev/null
+++ b/config/Android.mk
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VtsKernelConfig
+include test/vts/tools/build/Android.host_config.mk
\ No newline at end of file
diff --git a/config/AndroidTest.xml b/config/AndroidTest.xml
new file mode 100644
index 0000000..29d7c7e
--- /dev/null
+++ b/config/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 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.
+-->
+<configuration description="Config for VTS KernelConfigTest">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HostDrivenTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VtsKernelConfig" />
+        <option name="test-case-path" value="vts/testcases/kernel/config/VtsKernelConfigTest" />
+    </test>
+</configuration>
diff --git a/config/VtsKernelConfigTest.py b/config/VtsKernelConfigTest.py
new file mode 100644
index 0000000..ef70390
--- /dev/null
+++ b/config/VtsKernelConfigTest.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2017 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.
+#
+
+import gzip
+import logging
+import os
+import re
+import shutil
+import tempfile
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test
+from vts.runners.host import const
+from vts.runners.host import keys
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.file import file_utils
+
+
+class VtsKernelConfigTest(base_test.BaseTestClass):
+    """Test case which check config options in /proc/config.gz.
+
+    Attributes:
+        _temp_dir: The temporary directory to which /proc/config.gz is copied.
+    """
+
+    PROC_FILE_PATH = "/proc/config.gz"
+    KERNEL_CONFIG_FILE_PATH = "vts/testcases/kernel/config/data"
+    SUPPORTED_KERNEL_VERSIONS = ["3.18", "4.4", "4.9"]
+
+    def setUpClass(self):
+        required_params = [
+            keys.ConfigKeys.IKEY_DATA_FILE_PATH
+        ]
+        self.getUserParams(required_params)
+        self.dut = self.registerController(android_device)[0]
+        self.dut.shell.InvokeTerminal(
+            "KernelConfigTest")  # creates a remote shell instance.
+        self.shell = self.dut.shell.KernelConfigTest
+        self._temp_dir = tempfile.mkdtemp()
+
+    def checkKernelVersion(self):
+        """Validate the kernel version of DUT is a valid O kernel version.
+
+        Returns:
+            string, kernel version of device
+        """
+        cmd = "uname -a"
+        results = self.shell.Execute(cmd)
+        logging.info("Shell command '%s' results: %s", cmd, results)
+
+        match = re.search(r"\d+\.\d+", results[const.STDOUT][0])
+        if match is None:
+            asserts.fail("Failed to detect kernel version of device.")
+        else:
+            kernel_version = match.group(0)
+        logging.info("Detected kernel version: %s", kernel_version)
+
+        asserts.assertTrue(kernel_version in self.SUPPORTED_KERNEL_VERSIONS,
+                           "Detected kernel version '%s' is not one of %s"
+                           % (kernel_version, self.SUPPORTED_KERNEL_VERSIONS))
+
+        return kernel_version
+
+    def parseConfigFileToDict(self, file):
+        """Parse kernel config file to a dictionary.
+
+        Args:
+            file: file object, android-base.cfg or unzipped /proc/config.gz
+
+        Returns:
+            dict: {config_name: config_state}
+        """
+        config_lines = [line.rstrip("\n") for line in file.readlines()]
+        configs = dict()
+
+        for line in config_lines:
+            if line.startswith("#") and line.endswith("is not set"):
+                match = re.search(r"CONFIG_\S+", line)
+                if match is None:
+                    asserts.fail("Failed to parse config file")
+                else:
+                    config_name = match.group(0)
+                config_state = "n"
+            elif line.startswith("CONFIG_"):
+                config_name, config_state = line.split("=", 1)
+                if config_state.startswith(("'", '"')):
+                    config_state = config_state[1:-1]
+            else:
+                continue
+            configs[config_name] = config_state
+
+        return configs
+
+    def testKernelConfigs(self):
+        """Ensures all configs conform to android-base.cfg requirements.
+
+        Detects kernel version of device and validates against appropriate
+        Common Android Kernel android-base.cfg.
+        """
+        logging.info("Testing existence of %s" % self.PROC_FILE_PATH)
+        file_utils.assertPermissionsAndExistence(
+            self.shell, self.PROC_FILE_PATH, file_utils.IsReadOnly)
+
+        logging.info("Validating kernel version of device.")
+        kernel_version = self.checkKernelVersion()
+
+        config_file_path = os.path.join(self.data_file_path,
+            self.KERNEL_CONFIG_FILE_PATH, "android-" + kernel_version,
+            "android-base.cfg")
+        with open(config_file_path, 'r') as config_file:
+            configs = self.parseConfigFileToDict(config_file)
+
+        self.dut.adb.pull("%s %s" % (self.PROC_FILE_PATH, self._temp_dir))
+        logging.info("Adb pull %s to %s", self.PROC_FILE_PATH, self._temp_dir)
+
+        localpath = os.path.join(self._temp_dir, "config.gz")
+        with gzip.open(localpath, "rb") as device_config_file:
+            device_configs = self.parseConfigFileToDict(device_config_file)
+
+        should_be_enabled = []
+        should_not_be_set = []
+        incorrect_config_state = []
+        for config_name, config_state in configs.iteritems():
+            if (config_state == "y" and
+                (config_name not in device_configs or
+                 device_configs[config_name] not in ("y", "m"))):
+                should_be_enabled.append(config_name)
+            elif (config_state == "n" and (config_name in device_configs) and
+                  device_configs[config_name] != "n"):
+                should_not_be_set.append(config_name + "=" +
+                                         device_configs[config_name])
+            elif (config_name in device_configs and
+                  device_configs[config_name] != config_state):
+                incorrect_config_state.append(config_name + "=" +
+                                              device_configs[config_name])
+
+        asserts.assertTrue(
+            len(should_be_enabled) == 0 and len(should_not_be_set) == 0 and
+            len(incorrect_config_state) == 0,
+            ("The following kernel configs should be enabled: [%s]\n"
+             "The following kernel configs should not be set: [%s]\n"
+             "THe following kernel configs have incorrect state: [%s]") %
+            (", ".join(should_be_enabled), ", ".join(should_not_be_set),
+             ", ".join(incorrect_config_state)))
+
+    def tearDownClass(self):
+        """Deletes the temporary directory."""
+        logging.info("Delete %s", self._temp_dir)
+        shutil.rmtree(self._temp_dir)
+
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/config/__init__.py b/config/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/config/__init__.py
diff --git a/config/data/android-3.18/android-base.cfg b/config/data/android-3.18/android-base.cfg
new file mode 100644
index 0000000..4e305c7
--- /dev/null
+++ b/config/data/android-3.18/android-base.cfg
@@ -0,0 +1,170 @@
+#  KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWITCH=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/config/data/android-4.4/android-base.cfg b/config/data/android-4.4/android-base.cfg
new file mode 100644
index 0000000..2d08ea1
--- /dev/null
+++ b/config/data/android-4.4/android-base.cfg
@@ -0,0 +1,177 @@
+#  KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/config/data/android-4.9/android-base.cfg b/config/data/android-4.9/android-base.cfg
new file mode 100644
index 0000000..2d08ea1
--- /dev/null
+++ b/config/data/android-4.9/android-base.cfg
@@ -0,0 +1,177 @@
+#  KEEP ALPHABETICALLY SORTED
+# CONFIG_DEVKMEM is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_MODULES is not set
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_SYSVIPC is not set
+# CONFIG_USELIB is not set
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_DEVICES=binder,hwbinder,vndbinder
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_ASHMEM=y
+CONFIG_AUDIT=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_DEFAULT_SECURITY_SELINUX=y
+CONFIG_EMBEDDED=y
+CONFIG_FB=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_DIAG_DESTROY=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_INET=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_INET_ESP=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_TPROXY=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_CLS_U32=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_KEY=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_NAT=y
+CONFIG_NO_HZ=y
+CONFIG_PACKET=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PPP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PREEMPT=y
+CONFIG_PROFILING=y
+CONFIG_QFMT_V2=y
+CONFIG_QUOTA=y
+CONFIG_QUOTACTL=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QUOTA_TREE=y
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SECCOMP=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_STAGING=y
+CONFIG_SWP_EMULATION=y
+CONFIG_SYNC=y
+CONFIG_TUN=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_UNIX=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_XFRM_USER=y
\ No newline at end of file
diff --git a/ltp/ltp_configs.py b/ltp/ltp_configs.py
index 8413553..29568c7 100644
--- a/ltp/ltp_configs.py
+++ b/ltp/ltp_configs.py
@@ -180,6 +180,8 @@
 # Tests disabled
 # Based on external/ltp commit 5f01077afe994f4107b147222f3956716d4a8fde
 DISABLED_TESTS = [
+    # gunzip newly added on 4/12/17 and test is failing because -r option is not yet implemented.
+    'commands.gzip01',
     # b/32386191 getrusage04 result is flaky
     'syscalls.getrusage04',
     # b/31154962