Merge changes Ieb74d3fa,I7df3374f,Ia6894b63,I332af0d5 am: 7ce91a4ecd am: 6fe492cddd am: b761770c74
am: b917e1345e

Change-Id: Iab0dbac1c3727d9ef874a50258187b54e4f9aecf
diff --git a/vndk/tools/definition-tool/README.md b/vndk/tools/definition-tool/README.md
index 35a533e..bad020f 100644
--- a/vndk/tools/definition-tool/README.md
+++ b/vndk/tools/definition-tool/README.md
@@ -220,21 +220,30 @@
         --vendor ${ANDROID_PRODUCT_OUT}/vendor
 
 
-## Same-Process HAL
+## Same-Process NDK, Same-Process HAL, and VNDK-stable
 
-VNDK Definition Tool supports the same-process HAL definition as well.  To find
-same-process HALs, run `sp-hal` subcommand:
+VNDK Definition Tool can define the same-process HAL as well.  To find SP-NDK,
+SP-HAL, and VNDK-stable, run `sp-lib` subcommand:
 
-    $ python3 vndk_definition_tool.py sp-hal \
+    $ python3 vndk_definition_tool.py sp-lib \
         --system ${ANDROID_PRODUCT_OUT}/system \
         --vendor ${ANDROID_PRODUCT_OUT}/vendor
 
-To find the dependencies of same-process HALs, add `--closure` option:
+The output consists of following categories:
 
-    $ python3 vndk_definition_tool.py sp-hal \
-        --system ${ANDROID_PRODUCT_OUT}/system \
-        --vendor ${ANDROID_PRODUCT_OUT}/vendor
-        --closure
+* **sp-hal** -- Pre-defined same-process HALs.
+
+* **sp-hal-dep** -- Shared libraries that are used by SP-HALs.  These libraries
+  have to be installed into /vendor/lib[64]/sameprocess as well.
+
+* **sp-hal-vndk-stable** -- VNDK stable libraries that are used by SP-HAL.
+
+* **sp-ndk** -- Pre-defined same-process NDK libraries.
+
+* **sp-ndk-vndk-stable** -- Shared libraries that are used by SP-NDKs.
+
+**vndk-stable** is the union set of **sp-hal-vndk-stable** and
+**sp-ndk-vndk-stable**.
 
 
 ## Python 2 Support
diff --git a/vndk/tools/definition-tool/tests/test_elf_linker.py b/vndk/tools/definition-tool/tests/test_elf_linker.py
index 037e626..a7d571f 100755
--- a/vndk/tools/definition-tool/tests/test_elf_linker.py
+++ b/vndk/tools/definition-tool/tests/test_elf_linker.py
@@ -9,8 +9,8 @@
 import unittest
 
 from compat import StringIO
-from vndk_definition_tool import (BannedLibDict, ELF, ELFLinker, PT_SYSTEM,
-                                  PT_VENDOR)
+from vndk_definition_tool import (BannedLibDict, ELF, ELFLinker, GenericRefs,
+                                  PT_SYSTEM, PT_VENDOR)
 
 
 class GraphBuilder(object):
@@ -305,7 +305,7 @@
         self.assertNotIn('/system/lib/vndk-stable/libbar.so', vndk_stable)
         self.assertNotIn('/system/lib64/vndk-stable/libbar.so', vndk_stable)
 
-    def test_compute_sp_hal(self):
+    def test_compute_predefined_sp_hal(self):
         gb = GraphBuilder()
 
         # HIDL SP-HAL implementation.
@@ -323,6 +323,7 @@
 
         # OpenGL implementation.
         gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl')
+        gb.add_multilib(PT_VENDOR, 'libGLES_chipset', extra_dir='egl')
         gb.add_multilib(PT_VENDOR, 'libGLESv1_CM_chipset', extra_dir='egl')
         gb.add_multilib(PT_VENDOR, 'libGLESv2_chipset', extra_dir='egl')
         gb.add_multilib(PT_VENDOR, 'libGLESv3_chipset', extra_dir='egl')
@@ -341,7 +342,7 @@
         gb.resolve()
 
         # Compute SP-HAL.
-        sp_hals = set(lib.path for lib in gb.graph.compute_sp_hal(set(), False))
+        sp_hals = set(lib.path for lib in gb.graph.compute_predefined_sp_hal())
 
         for lib in ('lib', 'lib64'):
             # Check HIDL SP-HAL implementation.
@@ -361,6 +362,8 @@
 
             # Check that OpenGL implementations are SP-HALs.
             self.assertIn('/vendor/' + lib + '/egl/libEGL_chipset.so', sp_hals)
+            self.assertIn('/vendor/' + lib + '/egl/libGLES_chipset.so',
+                          sp_hals)
             self.assertIn('/vendor/' + lib + '/egl/libGLESv1_CM_chipset.so',
                           sp_hals)
             self.assertIn('/vendor/' + lib + '/egl/libGLESv2_chipset.so',
@@ -379,38 +382,101 @@
             self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
             self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
 
-    def test_compute_sp_hal_closure(self):
+    def test_copmute_sp_lib(self):
+        # Create graph.
         gb = GraphBuilder()
 
-        libc = gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libc')
+        # LL-NDK (should be excluded from result)
+        gb.add_multilib(PT_SYSTEM, 'libc')
 
-        libhidlbase = gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libhidlbase')
+        # SP-NDK VNDK-stable
+        gb.add_multilib(PT_SYSTEM, 'libcutils_dep', dt_needed=['libc.so'])
+        gb.add_multilib(PT_SYSTEM, 'libcutils',
+                        dt_needed=['libc.so', 'libcutils_dep.so'])
 
-        libhidltransport = gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64,
-                                      'libhidltransport')
+        # SP-NDK dependencies
+        gb.add_multilib(PT_SYSTEM, 'libutils',
+                        dt_needed=['libc.so', 'libcutils.so'])
 
-        gralloc_mapper = gb.add_lib(
-                PT_VENDOR, ELF.ELFCLASS64,
-                name='android.hardware.graphics.mapper@2.0-impl',
-                dt_needed=['libhidlbase.so', 'libhidltransport.so',
-                           'libc.so', 'gralloc_vnd.so'],
-                extra_dir='sameprocess')
+        # SP-NDK
+        gb.add_multilib(PT_SYSTEM, 'libEGL',
+                        dt_needed=['libc.so', 'libutils.so'])
 
-        gralloc_vnd = gb.add_lib(PT_VENDOR, ELF.ELFCLASS64, 'gralloc_vnd')
+        # SP-HAL dependencies
+        gb.add_multilib(PT_VENDOR, 'libllvm_vendor_dep')
+        gb.add_multilib(PT_VENDOR, 'libllvm_vendor',
+                        dt_needed=['libc.so', 'libllvm_vendor_dep.so'])
+
+        # SP-HAL VNDK-stable
+        gb.add_multilib(PT_SYSTEM, 'libhidlbase')
+        gb.add_multilib(PT_SYSTEM, 'libhidlmemory',
+                        dt_needed=['libhidlbase.so'])
+
+        # SP-HAL
+        gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl',
+                        dt_needed=['libc.so', 'libllvm_vendor.so',
+                                   'libhidlmemory.so'])
 
         gb.resolve()
 
-        vndk_stable = {libhidlbase, libhidltransport}
+        # Create generic reference.
+        class MockGenericRefs(object):
+            def classify_lib(self, lib):
+                if 'libllvm_vendor' in lib.path:
+                    return GenericRefs.NEW_LIB
+                return GenericRefs.EXPORT_EQUAL
 
-        sp_hal = gb.graph.compute_sp_hal(vndk_stable, closure=False)
-        sp_hal_closure = gb.graph.compute_sp_hal(vndk_stable, closure=True)
+        sp_hal, sp_hal_dep, sp_hal_vndk_stable, sp_ndk, sp_ndk_vndk_stable = \
+                gb.graph.compute_sp_lib(MockGenericRefs())
 
-        self.assertSetEqual({gralloc_mapper}, sp_hal)
+        self.assertEqual(2 * 1, len(sp_hal))
+        self.assertEqual(2 * 2, len(sp_hal_dep))
+        self.assertEqual(2 * 2, len(sp_hal_vndk_stable))
+        self.assertEqual(2 * 1, len(sp_ndk))
+        self.assertEqual(2 * 3, len(sp_ndk_vndk_stable))
 
-        self.assertSetEqual({gralloc_mapper, gralloc_vnd}, sp_hal_closure)
-        self.assertNotIn(libhidlbase, sp_hal_closure)
-        self.assertNotIn(libhidltransport, sp_hal_closure)
-        self.assertNotIn(libc, sp_hal_closure)
+        sp_hal = self._get_paths_from_nodes(sp_hal)
+        sp_hal_dep = self._get_paths_from_nodes(sp_hal_dep)
+        sp_hal_vndk_stable = self._get_paths_from_nodes(sp_hal_vndk_stable)
+        sp_ndk = self._get_paths_from_nodes(sp_ndk)
+        sp_ndk_vndk_stable = self._get_paths_from_nodes(sp_ndk_vndk_stable)
+
+        for lib_dir in ('lib', 'lib64'):
+            # SP-NDK dependencies
+            self.assertIn('/system/{}/libcutils.so'.format(lib_dir),
+                          sp_ndk_vndk_stable)
+            self.assertIn('/system/{}/libcutils_dep.so'.format(lib_dir),
+                          sp_ndk_vndk_stable)
+            self.assertIn('/system/{}/libutils.so'.format(lib_dir),
+                          sp_ndk_vndk_stable)
+
+            # SP-NDK
+            self.assertIn('/system/{}/libEGL.so'.format(lib_dir), sp_ndk)
+
+            # SP-HAL dependencies
+            self.assertIn('/vendor/{}/libllvm_vendor.so'.format(lib_dir),
+                          sp_hal_dep)
+            self.assertIn('/vendor/{}/libllvm_vendor_dep.so'.format(lib_dir),
+                          sp_hal_dep)
+
+            # SP-HAL VNDK-stable
+            self.assertIn('/system/{}/libhidlbase.so'.format(lib_dir),
+                          sp_hal_vndk_stable)
+            self.assertIn('/system/{}/libhidlmemory.so'.format(lib_dir),
+                          sp_hal_vndk_stable)
+
+            # SP-HAL
+            self.assertIn('/vendor/{}/egl/libEGL_chipset.so'.format(lib_dir),
+                          sp_hal)
+
+            # LL-NDK must be excluded.
+            libc_path = '/system/{}/libc.so'.format(lib_dir)
+            self.assertNotIn(libc_path, sp_hal)
+            self.assertNotIn(libc_path, sp_hal_dep)
+            self.assertNotIn(libc_path, sp_hal_vndk_stable)
+            self.assertNotIn(libc_path, sp_ndk)
+            self.assertNotIn(libc_path, sp_ndk_vndk_stable)
+
 
     def test_find_existing_vndk(self):
         gb = GraphBuilder()
diff --git a/vndk/tools/definition-tool/tests/test_ndk_libs.py b/vndk/tools/definition-tool/tests/test_ndk_libs.py
index 38a27cf..36c1720 100755
--- a/vndk/tools/definition-tool/tests/test_ndk_libs.py
+++ b/vndk/tools/definition-tool/tests/test_ndk_libs.py
@@ -12,83 +12,83 @@
 
 
 class NDKLibDictTest(unittest.TestCase):
-    def test_is_llndk(self):
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/libc.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/libdl.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/liblog.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/libm.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/libstdc++.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib/libz.so'))
+    def test_is_ll_ndk(self):
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libc.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libdl.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/liblog.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libm.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libstdc++.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib/libz.so'))
 
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/libc.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/libdl.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/liblog.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/libm.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/libstdc++.so'))
-        self.assertTrue(NDK_LIBS.is_llndk('/system/lib64/libz.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libc.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libdl.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/liblog.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libm.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libstdc++.so'))
+        self.assertTrue(NDK_LIBS.is_ll_ndk('/system/lib64/libz.so'))
 
-        self.assertFalse(NDK_LIBS.is_llndk('/system/lib/libz'))
-        self.assertFalse(NDK_LIBS.is_llndk('/system/lib/libzz.so'))
+        self.assertFalse(NDK_LIBS.is_ll_ndk('/system/lib/libz'))
+        self.assertFalse(NDK_LIBS.is_ll_ndk('/system/lib/libzz.so'))
 
-    def test_is_spndk(self):
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib/libEGL.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib/libGLESv1_CM.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib/libGLESv2.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib/libGLESv3.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib/libvulkan.so'))
+    def test_is_sp_ndk(self):
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libEGL.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libGLESv1_CM.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libGLESv2.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libGLESv3.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib/libvulkan.so'))
 
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib64/libEGL.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib64/libGLESv1_CM.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib64/libGLESv2.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib64/libGLESv3.so'))
-        self.assertTrue(NDK_LIBS.is_spndk('/system/lib64/libvulkan.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib64/libEGL.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib64/libGLESv1_CM.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib64/libGLESv2.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib64/libGLESv3.so'))
+        self.assertTrue(NDK_LIBS.is_sp_ndk('/system/lib64/libvulkan.so'))
 
         # Vendor libraries with the same name are still not SP-NDK.
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/libEGL.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/libGLESv1_CM.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/libGLESv2.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/libGLESv3.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/libEGL.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/libGLESv1_CM.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/libGLESv2.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/libGLESv3.so'))
 
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/egl/libEGL.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/egl/libGLESv1_CM.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/egl/libGLESv2.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/egl/libGLESv3.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/egl/libEGL.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/egl/libGLESv1_CM.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/egl/libGLESv2.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/egl/libGLESv3.so'))
 
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/libvulkan.so'))
-        self.assertFalse(NDK_LIBS.is_spndk('/vendor/lib64/vulkan.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/libvulkan.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/vendor/lib64/vulkan.so'))
 
         # LL-NDK is not SP-NDK.
-        self.assertFalse(NDK_LIBS.is_spndk('/system/lib/libc.so'))
+        self.assertFalse(NDK_LIBS.is_sp_ndk('/system/lib/libc.so'))
 
     def test_is_hlndk(self):
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libOpenMAXAL.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libOpenSLES.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libandroid.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libcamera2ndk.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libjnigraphics.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib/libmediandk.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libOpenMAXAL.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libOpenSLES.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libandroid.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libcamera2ndk.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libjnigraphics.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib/libmediandk.so'))
 
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libOpenMAXAL.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libOpenSLES.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libandroid.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libcamera2ndk.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libjnigraphics.so'))
-        self.assertTrue(NDK_LIBS.is_hlndk('/system/lib64/libmediandk.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libOpenMAXAL.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libOpenSLES.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libandroid.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libcamera2ndk.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libjnigraphics.so'))
+        self.assertTrue(NDK_LIBS.is_hl_ndk('/system/lib64/libmediandk.so'))
 
         # LL-NDK and SP-NDK are not HL-NDK.
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libc.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libEGL.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libGLESv1_CM.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libGLESv2.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libGLESv3.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib/libvulkan.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libc.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libEGL.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libGLESv1_CM.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libGLESv2.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libGLESv3.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib/libvulkan.so'))
 
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libc.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libEGL.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libGLESv1_CM.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libGLESv2.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libGLESv3.so'))
-        self.assertFalse(NDK_LIBS.is_hlndk('/system/lib64/libvulkan.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libc.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libEGL.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libGLESv1_CM.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libGLESv2.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libGLESv3.so'))
+        self.assertFalse(NDK_LIBS.is_hl_ndk('/system/lib64/libvulkan.so'))
 
     def test_is_ndk(self):
         # LL-NDK
@@ -134,6 +134,25 @@
         self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libmediandk.so'))
         self.assertTrue(NDK_LIBS.is_ndk('/system/lib64/libvulkan.so'))
 
+    def test_classify(self):
+        self.assertEqual(NDK_LIBS.NOT_NDK,
+                         NDK_LIBS.classify('/system/lib/libfoo.so'))
+        self.assertEqual(NDK_LIBS.LL_NDK,
+                         NDK_LIBS.classify('/system/lib/libc.so'))
+        self.assertEqual(NDK_LIBS.SP_NDK,
+                         NDK_LIBS.classify('/system/lib/libEGL.so'))
+        self.assertEqual(NDK_LIBS.HL_NDK,
+                         NDK_LIBS.classify('/system/lib/libmediandk.so'))
+
+        self.assertEqual(NDK_LIBS.NOT_NDK,
+                         NDK_LIBS.classify('/system/lib64/libfoo.so'))
+        self.assertEqual(NDK_LIBS.LL_NDK,
+                         NDK_LIBS.classify('/system/lib64/libc.so'))
+        self.assertEqual(NDK_LIBS.SP_NDK,
+                         NDK_LIBS.classify('/system/lib64/libEGL.so'))
+        self.assertEqual(NDK_LIBS.HL_NDK,
+                         NDK_LIBS.classify('/system/lib64/libmediandk.so'))
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/vndk/tools/definition-tool/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py
index c1a3032..644abb1 100755
--- a/vndk/tools/definition-tool/vndk_definition_tool.py
+++ b/vndk/tools/definition-tool/vndk_definition_tool.py
@@ -477,7 +477,12 @@
 #------------------------------------------------------------------------------
 
 class NDKLibDict(object):
-    LLNDK_LIB_NAMES = (
+    NOT_NDK = 0
+    LL_NDK = 1
+    SP_NDK = 2
+    HL_NDK = 3
+
+    LL_NDK_LIB_NAMES = (
         'libc.so',
         'libdl.so',
         'liblog.so',
@@ -486,7 +491,7 @@
         'libz.so',
     )
 
-    SPNDK_LIB_NAMES = (
+    SP_NDK_LIB_NAMES = (
         'libEGL.so',
         'libGLESv1_CM.so',
         'libGLESv2.so',
@@ -494,7 +499,7 @@
         'libvulkan.so',
     )
 
-    HLNDK_LIB_NAMES = (
+    HL_NDK_LIB_NAMES = (
         'libOpenMAXAL.so',
         'libOpenSLES.so',
         'libandroid.so',
@@ -504,30 +509,45 @@
     )
 
     @staticmethod
+    def _create_pattern(names):
+        return '|'.join('(?:^\\/system\\/lib(?:64)?\\/' + re.escape(i) + '$)'
+                        for i in names)
+
+    @staticmethod
     def _compile_path_matcher(names):
-        patts = '|'.join('(?:^\\/system\\/lib(?:64)?\\/' + re.escape(i) + '$)'
-                         for i in names)
-        return re.compile(patts)
+        return re.compile(NDKLibDict._create_pattern(names))
+
+    @staticmethod
+    def _compile_multi_path_matcher(name_lists):
+        patt = '|'.join('(' + NDKLibDict._create_pattern(names) + ')'
+                        for names in name_lists)
+        return re.compile(patt)
 
     def __init__(self):
-        self.llndk_patterns = self._compile_path_matcher(self.LLNDK_LIB_NAMES)
-        self.spndk_patterns = self._compile_path_matcher(self.SPNDK_LIB_NAMES)
-        self.hlndk_patterns = self._compile_path_matcher(self.HLNDK_LIB_NAMES)
-        self.ndk_patterns = self._compile_path_matcher(
-                self.LLNDK_LIB_NAMES + self.SPNDK_LIB_NAMES +
-                self.HLNDK_LIB_NAMES)
+        self.ll_ndk_patterns = self._compile_path_matcher(self.LL_NDK_LIB_NAMES)
+        self.sp_ndk_patterns = self._compile_path_matcher(self.SP_NDK_LIB_NAMES)
+        self.hl_ndk_patterns = self._compile_path_matcher(self.HL_NDK_LIB_NAMES)
+        self.ndk_patterns = self._compile_multi_path_matcher(
+                (self.LL_NDK_LIB_NAMES, self.SP_NDK_LIB_NAMES,
+                 self.HL_NDK_LIB_NAMES))
+
+    def is_ll_ndk(self, path):
+        return self.ll_ndk_patterns.match(path)
+
+    def is_sp_ndk(self, path):
+        return self.sp_ndk_patterns.match(path)
+
+    def is_hl_ndk(self, path):
+        return self.hl_ndk_patterns.match(path)
 
     def is_ndk(self, path):
         return self.ndk_patterns.match(path)
 
-    def is_llndk(self, path):
-        return self.llndk_patterns.match(path)
-
-    def is_spndk(self, path):
-        return self.spndk_patterns.match(path)
-
-    def is_hlndk(self, path):
-        return self.hlndk_patterns.match(path)
+    def classify(self, path):
+        match = self.ndk_patterns.match(path)
+        if not match:
+            return 0
+        return match.lastindex
 
 NDK_LIBS = NDKLibDict()
 
@@ -639,10 +659,26 @@
         self._deps = (set(), set())
         self._users = (set(), set())
         self.imported_ext_symbols = collections.defaultdict(set)
-        self.is_ndk = NDK_LIBS.is_ndk(path)
+        self._ndk_classification = NDK_LIBS.classify(path)
         self.unresolved_symbols = set()
         self.linked_symbols = dict()
 
+    @property
+    def is_ndk(self):
+        return self._ndk_classification != NDKLibDict.NOT_NDK
+
+    @property
+    def is_ll_ndk(self):
+        return self._ndk_classification == NDKLibDict.LL_NDK
+
+    @property
+    def is_sp_ndk(self):
+        return self._ndk_classification == NDKLibDict.SP_NDK
+
+    @property
+    def is_hl_ndk(self):
+        return self._ndk_classification == NDKLibDict.HL_NDK
+
     def add_dep(self, dst, ty):
         self._deps[ty].add(dst)
         dst._users[ty].add(self)
@@ -881,25 +917,14 @@
         self._resolve_lib_set_deps(
                 self.lib64, self.lib64_resolver, generic_refs)
 
-    def compute_matched_libs(self, path_patterns, closure=False,
-                             is_excluded_libs=None):
-        patt = re.compile('|'.join('(?:' + p + ')' for p in path_patterns))
-
-        # Find libraries with matching paths.
-        libs = set()
+    def all_lib(self):
         for lib_set in self.lib_pt:
             for lib in lib_set.values():
-                if patt.match(lib.path):
-                    libs.add(lib)
+                yield lib
 
-        if closure:
-            # Compute transitive closure.
-            if not is_excluded_libs:
-                def is_excluded_libs(lib):
-                    return False
-            libs = self.compute_closure(libs, is_excluded_libs)
-
-        return libs
+    def compute_path_matched_lib(self, path_patterns):
+        patt = re.compile('|'.join('(?:' + p + ')' for p in path_patterns))
+        return set(lib for lib in self.all_lib() if patt.match(lib.path))
 
     def compute_predefined_vndk_stable(self):
         """Find all vndk stable libraries."""
@@ -939,18 +964,15 @@
             '^.*/libvintf\\.so$',
         )
 
-        def is_excluded_libs(lib):
-            return lib.is_ndk
+        return self.compute_path_matched_lib(path_patterns)
 
-        return self.compute_matched_libs(path_patterns, False,
-                                         is_excluded_libs)
-
-    def compute_sp_hal(self, vndk_stable, closure):
+    def compute_predefined_sp_hal(self):
         """Find all same-process HALs."""
 
         path_patterns = (
             # OpenGL-related
             '^/vendor/.*/libEGL_.*\\.so$',
+            '^/vendor/.*/libGLES.*\\.so$',
             '^/vendor/.*/libGLESv1_CM_.*\\.so$',
             '^/vendor/.*/libGLESv2_.*\\.so$',
             '^/vendor/.*/libGLESv3_.*\\.so$',
@@ -964,11 +986,39 @@
             '^.*/android\\.hardware\\.graphics\\.mapper@\\d+\\.\\d+-impl\\.so$',
         )
 
-        def is_excluded_libs(lib):
-            return lib.is_ndk or lib in vndk_stable
+        return self.compute_path_matched_lib(path_patterns)
 
-        return self.compute_matched_libs(path_patterns, closure,
-                                         is_excluded_libs)
+    def compute_sp_ndk(self):
+        """Find all SP-NDK libraries."""
+        return set(lib for lib in self.all_lib() if lib.is_sp_ndk)
+
+    def compute_sp_lib(self, generic_refs):
+        def is_ndk(lib):
+            return lib.is_ndk
+
+        sp_ndk = self.compute_sp_ndk()
+        sp_ndk_closure = self.compute_closure(sp_ndk, is_ndk)
+
+        sp_hal = self.compute_predefined_sp_hal()
+        sp_hal_closure = self.compute_closure(sp_hal, is_ndk)
+
+        def is_aosp_lib(lib):
+            return (not generic_refs or \
+                    generic_refs.classify_lib(lib) != GenericRefs.NEW_LIB)
+
+        sp_hal_vndk_stable = set()
+        sp_hal_dep = set()
+        for lib in sp_hal_closure - sp_hal:
+            if is_aosp_lib(lib):
+                sp_hal_vndk_stable.add(lib)
+            else:
+                sp_hal_dep.add(lib)
+
+        sp_ndk_vndk_stable = sp_ndk_closure - sp_ndk
+        sp_hal_vndk_stable = sp_hal_vndk_stable - sp_ndk - sp_ndk_vndk_stable
+
+        return (sp_hal, sp_hal_dep, sp_hal_vndk_stable, sp_ndk, \
+                sp_ndk_vndk_stable)
 
     def _po_component_sorted(self, lib_set, get_successors,
                              get_strong_successors):
@@ -1404,7 +1454,7 @@
         # considered as banned libraries at the moment.
         def is_banned(lib):
             if lib.is_ndk:
-                return NDK_LIBS.is_hlndk(lib.path)
+                return lib.is_hl_ndk
             return (banned_libs.is_banned(lib.path) or
                     not lib.is_system_lib() or
                     not lib.path.endswith('.so'))
@@ -1683,7 +1733,7 @@
         for lib_set in lib_sets:
             for lib in lib_set:
                 for dep in lib.deps:
-                    if NDK_LIBS.is_hlndk(dep.path):
+                    if dep.is_hl_ndk:
                         print('warning: {}: VNDK is using high-level NDK {}.'
                                 .format(lib.path, dep.path), file=sys.stderr)
 
@@ -1735,14 +1785,16 @@
             self._warn_banned_vendor_lib_deps(graph, banned_libs)
 
         # Compute sp-hal and vndk-stable.
-        vndk_stable = graph.compute_predefined_vndk_stable()
-        sp_hals = graph.compute_sp_hal(vndk_stable, closure=False)
-        sp_hals_closure = graph.compute_sp_hal(vndk_stable, closure=True)
+        sp_hal, sp_hal_dep, sp_hal_vndk_stable, sp_ndk, sp_ndk_vndk_stable = \
+                graph.compute_sp_lib(generic_refs)
+
+        vndk_stable = sp_hal_vndk_stable | sp_ndk_vndk_stable
+        sp_hal_closure = sp_hal | sp_hal_dep
 
         # Normalize partition tags.  We expect many violations from the
         # pre-Treble world.  Guess a resolution for the incorrect partition
         # tag.
-        graph.normalize_partition_tags(sp_hals, generic_refs)
+        graph.normalize_partition_tags(sp_hal, generic_refs)
 
         # User may specify the partition for outward-customized vndk libs.  The
         # following code converts the path into ELFLinkData.
@@ -1768,7 +1820,7 @@
 
         # Compute vndk heuristics.
         vndk = graph.compute_vndk(
-                sp_hals_closure, vndk_stable, vndk_customized_for_system,
+                sp_hal_closure, vndk_stable, vndk_customized_for_system,
                 vndk_customized_for_vendor, generic_refs, banned_libs)
 
         if args.warn_high_level_ndk_deps:
@@ -1776,8 +1828,11 @@
                     (vndk.vndk_core, vndk.vndk_indirect, vndk.vndk_fwk_ext,
                      vndk.vndk_vnd_ext))
 
-        for lib in sorted_lib_path_list(sp_hals_closure):
-            print('sp-hals:', lib)
+        for lib in sorted_lib_path_list(sp_hal):
+            print('sp-hal:', lib)
+
+        for lib in sorted_lib_path_list(sp_hal_dep):
+            print('sp-hal-dep:', lib)
 
         for lib in sorted_lib_path_list(vndk_stable):
             print('vndk-stable:', lib)
@@ -1947,26 +2002,42 @@
         return 0
 
 
-class SpHalCommand(ELFGraphCommand):
+class SpLibCommand(ELFGraphCommand):
     def __init__(self):
-        super(SpHalCommand, self).__init__(
-                'sp-hal', help='Find transitive closure of same-process HALs')
+        super(SpLibCommand, self).__init__(
+                'sp-lib', help='Define sp-ndk, sp-hal, and vndk-stable')
 
     def add_argparser_options(self, parser):
-        super(SpHalCommand, self).add_argparser_options(parser)
+        super(SpLibCommand, self).add_argparser_options(parser)
 
-        parser.add_argument('--closure', action='store_true',
-                            help='show the closure')
+        parser.add_argument(
+                '--load-generic-refs',
+                help='compare with generic reference symbols')
 
     def main(self, args):
+        generic_refs = None
+        if args.load_generic_refs:
+            generic_refs = GenericRefs.create_from_dir(args.load_generic_refs)
+
         graph = ELFLinker.create(args.system, args.system_dir_as_vendor,
                                  args.vendor, args.vendor_dir_as_system,
                                  args.load_extra_deps)
 
-        vndk_stable = graph.compute_predefined_vndk_stable()
-        sp_hals = graph.compute_sp_hal(vndk_stable, closure=args.closure)
-        for lib in sorted_lib_path_list(sp_hals):
-            print(lib)
+        sp_hal, sp_hal_dep, sp_hal_vndk_stable, sp_ndk, sp_ndk_vndk_stable = \
+                graph.compute_sp_lib(generic_refs)
+
+        for lib in sorted_lib_path_list(sp_hal):
+            print('sp-hal:', lib)
+        for lib in sorted_lib_path_list(sp_hal_dep):
+            print('sp-hal-dep:', lib)
+        for lib in sorted_lib_path_list(sp_hal_vndk_stable):
+            print('sp-hal-vndk-stable:', lib)
+
+        for lib in sorted_lib_path_list(sp_ndk):
+            print('sp-ndk:', lib)
+        for lib in sorted_lib_path_list(sp_ndk_vndk_stable):
+            print('sp-ndk-vndk-stable:', lib)
+
         return 0
 
 
@@ -1986,7 +2057,7 @@
     register_subcmd(VNDKCapCommand())
     register_subcmd(DepsCommand())
     register_subcmd(DepsClosureCommand())
-    register_subcmd(SpHalCommand())
+    register_subcmd(SpLibCommand())
     register_subcmd(VNDKStableCommand())
 
     args = parser.parse_args()