def test_normalize_partition_tags_bad_vendor_deps(self):
        """Check whether normalize_partition_tags() hides the dependencies from
        the system partition to the vendor partition if the dependencies are
        not SP-HAL libraries."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk', dt_needed=['libvnd.so'])
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd')
        gb.resolve()

        self.assertIn(libvnd, libfwk.deps_needed)
        self.assertIn(libfwk, libvnd.users_needed)

        stderr = StringIO()
        with patch('sys.stderr', stderr):
            gb.graph.normalize_partition_tags(set(), None)

        self.assertRegexpMatches(
                stderr.getvalue(),
                'error: .*: system exe/lib must not depend on vendor lib .*.  '
                'Assume such dependency does not exist.')

        self.assertNotIn(libvnd, libfwk.deps_needed)
        self.assertNotIn(libfwk, libvnd.users_needed)

        self.assertIn(libvnd, libfwk.deps_needed_hidden)
        self.assertIn(libfwk, libvnd.users_needed_hidden)

        self.assertIn(libvnd, libfwk.deps_all)
        self.assertIn(libvnd, libfwk.deps_needed_all)
        self.assertNotIn(libvnd, libfwk.deps_good)

        self.assertIn(libfwk, libvnd.users_all)
        self.assertIn(libfwk, libvnd.users_needed_all)
        self.assertNotIn(libfwk, libvnd.users_good)
示例#2
0
    def test_unresolved_symbols(self):
        gb = GraphBuilder()
        gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[],
                   exported_symbols={'foo', 'bar'},
                   imported_symbols={'__does_not_exist'})
        gb.resolve()

        lib = gb.graph.get_lib('/system/lib64/libfoo.so')
        self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
    def test_vndk_bad_vendor_deps(self):
        """Check the computation of vndk without generic references."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk')
        libvndk = gb.add_lib32(PT_SYSTEM,
                               'libvndk',
                               dt_needed=['libvnd_bad.so'],
                               extra_dir='vndk')
        libvndk_sp = gb.add_lib32(PT_SYSTEM,
                                  'libutils',
                                  dt_needed=['libvnd_bad.so'],
                                  extra_dir='vndk-sp')
        libvnd = gb.add_lib32(PT_VENDOR,
                              'libvnd',
                              dt_needed=['libvndk.so', 'libutils.so'])
        libvnd_bad = gb.add_lib32(PT_VENDOR, 'libvnd_bad', extra_dir='vndk-sp')
        gb.resolve()

        self.assertIn(libvnd_bad, libvndk.deps_all)
        self.assertIn(libvnd_bad, libvndk_sp.deps_all)

        with patch('sys.stderr', StringIO()):
            vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertNotIn(libvnd_bad, vndk_sets.vndk)
        self.assertNotIn(libvnd_bad, vndk_sets.vndk_sp)
    def test_serialize_data_with_all_deps(self):
        """compute_degenerated_vndk() should not remove bad dependencies from
        the output of deps-insight.  This test checks the existance of bad
        dependencies."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk')
        libvndk = gb.add_lib32(PT_SYSTEM, 'libvndk',
                               dt_needed=['libvnd_bad.so'], extra_dir='vndk')
        libvndk_sp = gb.add_lib32(PT_SYSTEM, 'libutils',
                                  dt_needed=['libvnd_bad.so'],
                                  extra_dir='vndk-sp')
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd',
                              dt_needed=['libvndk.so', 'libutils.so'])
        libvnd_bad = gb.add_lib32(PT_VENDOR, 'libvnd_bad', extra_dir='vndk-sp')
        gb.resolve()

        with patch('sys.stderr', StringIO()):
            vndk_sets = gb.graph.compute_degenerated_vndk(set(), None)

        self.assertNotIn(libvnd_bad, libvndk.deps_good)
        self.assertNotIn(libvnd_bad, libvndk_sp.deps_good)

        strs, mods = DepsInsightCommand.serialize_data(
                list(gb.graph.all_libs()), vndk_sets, ModuleInfo())

        deps = self._get_module_deps(strs, mods, libvndk.path)
        self.assertIn(libvnd_bad.path, deps)

        deps = self._get_module_deps(strs, mods, libvndk_sp.path)
        self.assertIn(libvnd_bad.path, deps)

        users = self._get_module_users(strs, mods, libvnd_bad.path)
        self.assertIn(libvndk.path, users)
        self.assertIn(libvndk_sp.path, users)
示例#5
0
    def test_add_dlopen_deps_lib_subst(self):
        gb = GraphBuilder()
        liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
        libb_32, libb_64 = gb.add_multilib(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/${LIB}/liba.so: /system/${LIB}/libb.so')
            tmp_file.seek(0)
            gb.graph.add_dlopen_deps(tmp_file.name)

        self.assertIn(libb_32, liba_32.deps_dlopen)
        self.assertIn(liba_32, libb_32.users_dlopen)

        self.assertIn(libb_64, liba_64.deps_dlopen)
        self.assertIn(liba_64, libb_64.users_dlopen)
示例#6
0
    def test_add_dlopen_deps(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/lib/liba.so: /system/lib/libb.so')
            tmp_file.seek(0)
            gb.graph.add_dlopen_deps(tmp_file.name)

        self.assertIn(libb, liba.deps_dlopen)
        self.assertIn(liba, libb.users_dlopen)

        self.assertNotIn(libb, liba.deps_needed)
        self.assertNotIn(liba, libb.users_needed)
示例#7
0
    def test_add_dlopen_deps(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/lib/liba.so: /system/lib/libb.so')
            tmp_file.seek(0)
            gb.graph.add_dlopen_deps(tmp_file.name)

        self.assertIn(libb, liba.deps_dlopen)
        self.assertIn(liba, libb.users_dlopen)

        self.assertNotIn(libb, liba.deps_needed)
        self.assertNotIn(liba, libb.users_needed)
示例#8
0
    def test_add_dlopen_deps_lib_subst(self):
        gb = GraphBuilder()
        liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
        libb_32, libb_64 = gb.add_multilib(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/${LIB}/liba.so: /system/${LIB}/libb.so')
            tmp_file.seek(0)
            gb.graph.add_dlopen_deps(tmp_file.name)

        self.assertIn(libb_32, liba_32.deps_dlopen)
        self.assertIn(liba_32, libb_32.users_dlopen)

        self.assertIn(libb_64, liba_64.deps_dlopen)
        self.assertIn(liba_64, libb_64.users_dlopen)
    def test_add_dlopen_deps_error(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/lib/libc.so: /system/lib/libd.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertRegexpMatches(
                    stderr.getvalue(),
                    'error: Failed to add dlopen dependency from .* to .*\\.\n')
示例#10
0
    def test_normalize_partition_tags_sp_hal(self):
        """Check whether normalize_partition_tags() keep dependencies to SP-HAL
        libraries as-is."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk', dt_needed=['libsphal.so'])
        libsphal = gb.add_lib32(PT_VENDOR, 'libsphal')
        gb.resolve()

        self.assertIn(libsphal, libfwk.deps_needed)
        self.assertIn(libfwk, libsphal.users_needed)

        gb.graph.normalize_partition_tags({libsphal}, None)

        # SP-HALs should be kept as-is.
        self.assertIn(libsphal, libfwk.deps_needed)
        self.assertIn(libfwk, libsphal.users_needed)
示例#11
0
    def test_add_dlopen_deps_error(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/lib/libc.so: /system/lib/libd.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertRegexpMatches(
                stderr.getvalue(), 'error:' + re.escape(tmp_file.name) +
                ':1: ' + 'Failed to add dlopen dependency from .* to .*\\.\n')
示例#12
0
    def test_add_dlopen_deps_regex(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('[regex].*libb\\.so: [regex].*/${LIB}/liba\\.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertEqual('', stderr.getvalue())

        self.assertIn(liba, libb.deps_dlopen)
        self.assertIn(libb, liba.users_dlopen)
示例#13
0
    def test_add_dlopen_deps_regex(self):
        gb = GraphBuilder()
        liba = gb.add_lib32(PT_SYSTEM, 'liba')
        libb = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('[regex].*libb\\.so: [regex].*/${LIB}/liba\\.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertEqual('', stderr.getvalue())

        self.assertIn(liba, libb.deps_dlopen)
        self.assertIn(libb, liba.users_dlopen)
示例#14
0
    def test_add_dlopen_deps_lib_subset_single_bitness(self):
        gb = GraphBuilder()
        liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
        libb_32 = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/${LIB}/libb.so: /system/${LIB}/liba.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertEqual('', stderr.getvalue())

        self.assertIn(liba_32, libb_32.deps_dlopen)
        self.assertIn(libb_32, liba_32.users_dlopen)

        self.assertEqual(0, len(liba_64.users_dlopen))
示例#15
0
    def test_normalize_partition_tags_bad_vendor_deps(self):
        """Check whether normalize_partition_tags() hides the dependencies from
        the system partition to the vendor partition if the dependencies are
        not SP-HAL libraries."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk', dt_needed=['libvnd.so'])
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd')
        gb.resolve()

        self.assertIn(libvnd, libfwk.deps_needed)
        self.assertIn(libfwk, libvnd.users_needed)

        stderr = StringIO()
        with patch('sys.stderr', stderr):
            gb.graph.normalize_partition_tags(set(), None)

        self.assertRegex(
                stderr.getvalue(),
                'error: .*: system exe/lib must not depend on vendor lib .*.  '
                'Assume such dependency does not exist.')

        self.assertNotIn(libvnd, libfwk.deps_needed)
        self.assertNotIn(libfwk, libvnd.users_needed)

        self.assertIn(libvnd, libfwk.deps_needed_hidden)
        self.assertIn(libfwk, libvnd.users_needed_hidden)

        self.assertIn(libvnd, libfwk.deps_all)
        self.assertIn(libvnd, libfwk.deps_needed_all)
        self.assertNotIn(libvnd, libfwk.deps_good)

        self.assertIn(libfwk, libvnd.users_all)
        self.assertIn(libfwk, libvnd.users_needed_all)
        self.assertNotIn(libfwk, libvnd.users_good)
示例#16
0
    def test_unresolved_symbols(self):
        gb = GraphBuilder()
        gb.add_lib(PT_SYSTEM, ELF.ELFCLASS64, 'libfoo', dt_needed=[],
                   exported_symbols={'foo', 'bar'},
                   imported_symbols={'__does_not_exist'})
        gb.resolve()

        lib = gb.graph.get_lib('/system/lib64/libfoo.so')
        self.assertEqual({'__does_not_exist'}, lib.unresolved_symbols)
示例#17
0
    def test_vndk(self):
        """Check the computation of vndk without generic references."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk')
        libvndk = gb.add_lib32(PT_SYSTEM, 'libvndk', extra_dir='vndk')
        libvndk_sp = gb.add_lib32(PT_SYSTEM, 'libutils', extra_dir='vndk-sp')
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd',
                              dt_needed=['libvndk.so', 'libutils.so'])
        gb.resolve()

        self.assertIn(libvndk, libvnd.deps_all)
        self.assertIn(libvndk_sp, libvnd.deps_all)

        vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertIn(libvndk, vndk_sets.vndk)
        self.assertIn(libvndk_sp, vndk_sets.vndk_sp)
示例#18
0
    def test_vndk(self):
        """Check the computation of vndk without generic references."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk')
        libvndk = gb.add_lib32(PT_SYSTEM, 'libvndk', extra_dir='vndk')
        libvndk_sp = gb.add_lib32(PT_SYSTEM, 'libutils', extra_dir='vndk-sp')
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd',
                              dt_needed=['libvndk.so', 'libutils.so'])
        gb.resolve()

        self.assertIn(libvndk, libvnd.deps_all)
        self.assertIn(libvndk_sp, libvnd.deps_all)

        vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertIn(libvndk, vndk_sets.vndk)
        self.assertIn(libvndk_sp, vndk_sets.vndk_sp)
示例#19
0
    def test_vndk_bad_vendor_deps(self):
        """Check the computation of vndk without generic references."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk')
        libvndk = gb.add_lib32(PT_SYSTEM, 'libvndk',
                               dt_needed=['libvnd_bad.so'], extra_dir='vndk')
        libvndk_sp = gb.add_lib32(PT_SYSTEM, 'libutils',
                                  dt_needed=['libvnd_bad.so'],
                                  extra_dir='vndk-sp')
        libvnd = gb.add_lib32(PT_VENDOR, 'libvnd',
                              dt_needed=['libvndk.so', 'libutils.so'])
        libvnd_bad = gb.add_lib32(PT_VENDOR, 'libvnd_bad', extra_dir='vndk-sp')
        gb.resolve()

        self.assertIn(libvnd_bad, libvndk.deps_all)
        self.assertIn(libvnd_bad, libvndk_sp.deps_all)

        with patch('sys.stderr', StringIO()):
            vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertNotIn(libvnd_bad, vndk_sets.vndk)
        self.assertNotIn(libvnd_bad, vndk_sets.vndk_sp)
示例#20
0
    def test_normalize_partition_tags_sp_hal(self):
        """Check whether normalize_partition_tags() keep dependencies to SP-HAL
        libraries as-is."""

        gb = GraphBuilder()
        libfwk = gb.add_lib32(PT_SYSTEM, 'libfwk', dt_needed=['libsphal.so'])
        libsphal = gb.add_lib32(PT_VENDOR, 'libsphal')
        gb.resolve()

        self.assertIn(libsphal, libfwk.deps_needed)
        self.assertIn(libfwk, libsphal.users_needed)

        gb.graph.normalize_partition_tags({libsphal}, None)

        # SP-HALs should be kept as-is.
        self.assertIn(libsphal, libfwk.deps_needed)
        self.assertIn(libfwk, libsphal.users_needed)
示例#21
0
    def test_sp_ndk_indirect_without_sp_hal(self):
        """Check the computation of sp_ndk_indirect excludes sp_hal."""

        gb = GraphBuilder()
        libEGL = gb.add_lib32(PT_SYSTEM, 'libEGL', dt_needed=['libEGL_dep.so'])
        libEGL_dep = gb.add_lib32(PT_SYSTEM, 'libEGL_dep')
        libEGL_chipset = gb.add_lib32(PT_VENDOR,
                                      'libEGL_chipset',
                                      extra_dir='egl',
                                      dt_needed=['libEGL.so'])
        gb.resolve()

        libEGL.add_dlopen_dep(libEGL_chipset)

        vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertIn(libEGL, vndk_sets.sp_ndk)
        self.assertIn(libEGL_dep, vndk_sets.sp_ndk_indirect)
        self.assertIn(libEGL_chipset, vndk_sets.sp_hal)

        self.assertNotIn(libEGL_chipset, vndk_sets.sp_ndk_indirect)
示例#22
0
    def test_add_dlopen_deps_lib_subset_single_bitness(self):
        gb = GraphBuilder()
        liba_32, liba_64 = gb.add_multilib(PT_SYSTEM, 'liba')
        libb_32 = gb.add_lib32(PT_SYSTEM, 'libb')
        gb.resolve()

        with tempfile.NamedTemporaryFile(mode='w') as tmp_file:
            tmp_file.write('/system/${LIB}/libb.so: /system/${LIB}/liba.so')
            tmp_file.seek(0)

            stderr = StringIO()
            with patch('sys.stderr', stderr):
                gb.graph.add_dlopen_deps(tmp_file.name)

            self.assertEqual('', stderr.getvalue())

        self.assertIn(liba_32, libb_32.deps_dlopen)
        self.assertIn(libb_32, liba_32.users_dlopen)

        self.assertEqual(0, len(liba_64.users_dlopen))
示例#23
0
    def test_sp_ndk_indirect_without_sp_hal(self):
        """Check the computation of sp_ndk_indirect excludes sp_hal."""

        gb = GraphBuilder()
        libEGL = gb.add_lib32(PT_SYSTEM, 'libEGL',
                              dt_needed=['libEGL_dep.so'])
        libEGL_dep = gb.add_lib32(PT_SYSTEM, 'libEGL_dep')
        libEGL_chipset = gb.add_lib32(PT_VENDOR, 'libEGL_chipset',
                                      extra_dir='egl',
                                      dt_needed=['libEGL.so'])
        gb.resolve()

        libEGL.add_dlopen_dep(libEGL_chipset)

        vndk_sets = gb.graph.compute_degenerated_vndk(None)

        self.assertIn(libEGL, vndk_sets.sp_ndk)
        self.assertIn(libEGL_dep, vndk_sets.sp_ndk_indirect)
        self.assertIn(libEGL_chipset, vndk_sets.sp_hal)

        self.assertNotIn(libEGL_chipset, vndk_sets.sp_ndk_indirect)
示例#24
0
    def _create_normal_graph(self):
        gb = GraphBuilder()

        gb.add_multilib(PT_SYSTEM,
                        'libdl',
                        exported_symbols={'dlclose', 'dlopen', 'dlsym'})

        gb.add_multilib(PT_SYSTEM, 'libm', exported_symbols={'cos', 'sin'})

        gb.add_multilib(PT_SYSTEM,
                        'libc',
                        dt_needed=['libdl.so', 'libm.so'],
                        exported_symbols={'fclose', 'fopen', 'fread'},
                        imported_symbols={'dlclose', 'dlopen', 'cos', 'sin'})

        gb.add_multilib(PT_SYSTEM,
                        'libRS',
                        dt_needed=['libdl.so'],
                        exported_symbols={'rsContextCreate'},
                        imported_symbols={'dlclose', 'dlopen', 'dlsym'})

        gb.add_multilib(
            PT_SYSTEM,
            'libcutils',
            dt_needed=['libc.so', 'libdl.so'],
            imported_symbols={'dlclose', 'dlopen', 'fclose', 'fopen'})

        gb.add_multilib(PT_VENDOR,
                        'libEGL',
                        dt_needed=['libc.so', 'libcutils.so', 'libdl.so'],
                        exported_symbols={'eglGetDisplay'},
                        imported_symbols={'fclose', 'fopen'})

        gb.resolve()
        return gb
示例#25
0
    def test_compute_predefined_sp_hal(self):
        gb = GraphBuilder()

        # HIDL SP-HAL implementation.
        gb.add_multilib(PT_SYSTEM, 'gralloc.default', extra_dir='hw')
        gb.add_multilib(PT_SYSTEM, 'gralloc.chipset', extra_dir='hw')
        gb.add_multilib(PT_SYSTEM,
                        '[email protected]',
                        extra_dir='hw')

        # NDK loader libraries should not be considered as SP-HALs.
        gb.add_multilib(PT_SYSTEM, 'libvulkan')
        gb.add_multilib(PT_SYSTEM, 'libEGL')
        gb.add_multilib(PT_SYSTEM, 'libGLESv1_CM')
        gb.add_multilib(PT_SYSTEM, 'libGLESv2')
        gb.add_multilib(PT_SYSTEM, 'libGLESv3')

        # 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')

        # Renderscript implementation.
        gb.add_multilib(PT_VENDOR, 'libRSDriver_chipset')
        gb.add_multilib(PT_VENDOR, 'libPVRRS')

        # Vulkan implementation.
        gb.add_multilib(PT_VENDOR, 'vulkan.chipset', extra_dir='hw')

        # Some un-related libraries.
        gb.add_multilib(PT_SYSTEM, 'libfoo')
        gb.add_multilib(PT_VENDOR, 'libfoo')

        gb.resolve()

        # Compute SP-HAL.
        sp_hals = set(lib.path for lib in gb.graph.compute_predefined_sp_hal())

        for lib in ('lib', 'lib64'):
            # Check HIDL SP-HAL implementation.
            self.assertIn('/system/' + lib + '/hw/gralloc.default.so', sp_hals)
            self.assertIn('/system/' + lib + '/hw/gralloc.chipset.so', sp_hals)
            self.assertIn(
                '/system/' + lib + '/hw/'
                '*****@*****.**', sp_hals)

            # Check that NDK loaders are not SP-HALs.
            self.assertNotIn('/system/' + lib + '/libvulkan.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libEGL.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv1_CM.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv2.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv3.so', sp_hals)

            # 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',
                          sp_hals)
            self.assertIn('/vendor/' + lib + '/egl/libGLESv3_chipset.so',
                          sp_hals)

            # Check that Renderscript implementations are SP-HALs.
            self.assertIn('/vendor/' + lib + '/libRSDriver_chipset.so',
                          sp_hals)
            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)

            # Check that vulkan implementation are SP-HALs.
            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)

            # Check that un-related libraries are not SP-HALs.
            self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
            self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)
示例#26
0
    def test_compute_sp_lib(self):
        # Create graph.
        gb = GraphBuilder()

        # LL-NDK (should be excluded from result)
        gb.add_multilib(PT_SYSTEM, 'libc')

        libEGL_32, libEGL_64 = \
                gb.add_multilib(PT_SYSTEM, 'libEGL',
                                dt_needed=['libc.so', 'libutils.so'])

        # LL-NDK dependencies
        gb.add_multilib(PT_SYSTEM,
                        'libutils',
                        dt_needed=['libc.so', 'libcutils.so'])

        # VNDK-SP used by both LL-NDK and SP-HAL
        gb.add_multilib(PT_SYSTEM, 'libsp_both_vs')

        # VNDK-SP used by LL-NDK
        gb.add_multilib(PT_SYSTEM, 'libcutils_dep', dt_needed=['libc.so'])
        gb.add_multilib(
            PT_SYSTEM,
            'libcutils',
            dt_needed=['libc.so', 'libcutils_dep.so', 'libsp_both_vs.so'])

        # VNDK-SP used by SP-HAL
        gb.add_multilib(PT_SYSTEM, 'libhidlbase')
        gb.add_multilib(PT_SYSTEM,
                        'libhidlmemory',
                        dt_needed=['libhidlbase.so', 'libsp_both_vs.so'])

        # 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
        libEGL_chipset_32, libEGL_chipset_64 = \
                gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl',
                                dt_needed=['libc.so', 'libllvm_vendor.so',
                                           'libhidlmemory.so'])

        gb.resolve()

        # Add dlopen() dependencies from libEGL to libEGL_chipset.
        libEGL_32.add_dlopen_dep(libEGL_chipset_32)
        libEGL_64.add_dlopen_dep(libEGL_chipset_64)

        # 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_lib = gb.graph.compute_sp_lib(MockGenericRefs())

        self.assertEqual(2 * 1, len(sp_lib.sp_hal))
        self.assertEqual(2 * 2, len(sp_lib.sp_hal_dep))
        self.assertEqual(2 * 2, len(sp_lib.vndk_sp_hal))
        self.assertEqual(2 * 2, len(sp_lib.ll_ndk))
        self.assertEqual(2 * 3, len(sp_lib.ll_ndk_indirect))
        self.assertEqual(2 * 1, len(sp_lib.vndk_sp_both))

        sp_hal = self._get_paths_from_nodes(sp_lib.sp_hal)
        sp_hal_dep = self._get_paths_from_nodes(sp_lib.sp_hal_dep)
        vndk_sp_hal = self._get_paths_from_nodes(sp_lib.vndk_sp_hal)

        ll_ndk = self._get_paths_from_nodes(sp_lib.ll_ndk)
        ll_ndk_indirect = self._get_paths_from_nodes(sp_lib.ll_ndk_indirect)

        vndk_sp_both = self._get_paths_from_nodes(sp_lib.vndk_sp_both)

        for lib_dir in ('lib', 'lib64'):
            # VNDK-SP used by both LL-NDK and SP-HAL
            self.assertIn('/system/{}/libsp_both_vs.so'.format(lib_dir),
                          vndk_sp_both)

            # VNDK-SP used by LL-NDK
            self.assertIn('/system/{}/libcutils.so'.format(lib_dir),
                          ll_ndk_indirect)
            self.assertIn('/system/{}/libcutils_dep.so'.format(lib_dir),
                          ll_ndk_indirect)
            self.assertIn('/system/{}/libutils.so'.format(lib_dir),
                          ll_ndk_indirect)

            # VNDK-SP used by SP-HAL
            self.assertIn('/system/{}/libhidlbase.so'.format(lib_dir),
                          vndk_sp_hal)
            self.assertIn('/system/{}/libhidlmemory.so'.format(lib_dir),
                          vndk_sp_hal)

            # 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
            self.assertIn('/vendor/{}/egl/libEGL_chipset.so'.format(lib_dir),
                          sp_hal)

            # LL-NDK
            self.assertIn('/system/{}/libEGL.so'.format(lib_dir), ll_ndk)
            self.assertIn('/system/{}/libc.so'.format(lib_dir), ll_ndk)

            # LL-NDK must not in sp_hal, sp_hal_dep, and vndk_sp_hal.
            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, vndk_sp_hal)
            self.assertNotIn(libc_path, ll_ndk_indirect)
示例#27
0
    def test_link_vndk_ver_dirs(self):
        gb = GraphBuilder()

        libc_32, libc_64 = gb.add_multilib(PT_SYSTEM, 'libc')

        libvndk_a_32, libvndk_a_64 = gb.add_multilib(
            PT_SYSTEM,
            'libvndk_a',
            extra_dir='vndk-28',
            dt_needed=['libc.so', 'libvndk_b.so', 'libvndk_sp_b.so'])

        libvndk_b_32, libvndk_b_64 = gb.add_multilib(
            PT_SYSTEM,
            'libvndk_b',
            extra_dir='vndk-28',
            dt_needed=['libc.so', 'libvndk_sp_b.so'])

        libvndk_c_32, libvndk_c_64 = gb.add_multilib(
            PT_VENDOR,
            'libvndk_c',
            extra_dir='vndk-28',
            dt_needed=['libc.so', 'libvndk_d.so', 'libvndk_sp_d.so'])

        libvndk_d_32, libvndk_d_64 = gb.add_multilib(
            PT_VENDOR,
            'libvndk_d',
            extra_dir='vndk-28',
            dt_needed=['libc.so', 'libvndk_sp_d.so'])

        libvndk_sp_a_32, libvndk_sp_a_64 = gb.add_multilib(
            PT_SYSTEM,
            'libvndk_sp_a',
            extra_dir='vndk-sp-28',
            dt_needed=['libc.so', 'libvndk_sp_b.so'])

        libvndk_sp_b_32, libvndk_sp_b_64 = gb.add_multilib(
            PT_SYSTEM,
            'libvndk_sp_b',
            extra_dir='vndk-sp-28',
            dt_needed=['libc.so'])

        libvndk_sp_c_32, libvndk_sp_c_64 = gb.add_multilib(
            PT_VENDOR,
            'libvndk_sp_c',
            extra_dir='vndk-sp-28',
            dt_needed=['libc.so', 'libvndk_sp_d.so'])

        libvndk_sp_d_32, libvndk_sp_d_64 = gb.add_multilib(
            PT_VENDOR,
            'libvndk_sp_d',
            extra_dir='vndk-sp-28',
            dt_needed=['libc.so'])

        gb.resolve(VNDKLibDir.create_from_version('28'), '28')

        # 32-bit shared libraries
        self.assertIn(libc_32, libvndk_a_32.deps_all)
        self.assertIn(libc_32, libvndk_b_32.deps_all)
        self.assertIn(libc_32, libvndk_c_32.deps_all)
        self.assertIn(libc_32, libvndk_d_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_a_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_b_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_c_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_d_32.deps_all)

        self.assertIn(libvndk_b_32, libvndk_a_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_a_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_b_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_sp_a_32.deps_all)

        self.assertIn(libvndk_d_32, libvndk_c_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_c_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_d_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_sp_c_32.deps_all)

        # 64-bit shared libraries
        self.assertIn(libc_64, libvndk_a_64.deps_all)
        self.assertIn(libc_64, libvndk_b_64.deps_all)
        self.assertIn(libc_64, libvndk_c_64.deps_all)
        self.assertIn(libc_64, libvndk_d_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_a_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_b_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_c_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_d_64.deps_all)

        self.assertIn(libvndk_b_64, libvndk_a_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_a_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_b_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_sp_a_64.deps_all)

        self.assertIn(libvndk_d_64, libvndk_c_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_c_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_d_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_sp_c_64.deps_all)
示例#28
0
    def test_link_vndk_ver_dirs(self):
        gb = GraphBuilder()

        libc_32, libc_64 = gb.add_multilib(PT_SYSTEM, 'libc')

        libvndk_a_32, libvndk_a_64 = gb.add_multilib(
                PT_SYSTEM, 'libvndk_a', extra_dir='vndk-28',
                dt_needed=['libc.so', 'libvndk_b.so', 'libvndk_sp_b.so'])

        libvndk_b_32, libvndk_b_64 = gb.add_multilib(
                PT_SYSTEM, 'libvndk_b', extra_dir='vndk-28',
                dt_needed=['libc.so', 'libvndk_sp_b.so'])

        libvndk_c_32, libvndk_c_64 = gb.add_multilib(
                PT_VENDOR, 'libvndk_c', extra_dir='vndk-28',
                dt_needed=['libc.so', 'libvndk_d.so', 'libvndk_sp_d.so'])

        libvndk_d_32, libvndk_d_64 = gb.add_multilib(
                PT_VENDOR, 'libvndk_d', extra_dir='vndk-28',
                dt_needed=['libc.so', 'libvndk_sp_d.so'])

        libvndk_sp_a_32, libvndk_sp_a_64 = gb.add_multilib(
                PT_SYSTEM, 'libvndk_sp_a', extra_dir='vndk-sp-28',
                dt_needed=['libc.so', 'libvndk_sp_b.so'])

        libvndk_sp_b_32, libvndk_sp_b_64 = gb.add_multilib(
                PT_SYSTEM, 'libvndk_sp_b', extra_dir='vndk-sp-28',
                dt_needed=['libc.so'])

        libvndk_sp_c_32, libvndk_sp_c_64 = gb.add_multilib(
                PT_VENDOR, 'libvndk_sp_c', extra_dir='vndk-sp-28',
                dt_needed=['libc.so', 'libvndk_sp_d.so'])

        libvndk_sp_d_32, libvndk_sp_d_64 = gb.add_multilib(
                PT_VENDOR, 'libvndk_sp_d', extra_dir='vndk-sp-28',
                dt_needed=['libc.so'])

        gb.resolve(VNDKLibDir.create_from_version('28'), '28')

        # 32-bit shared libraries
        self.assertIn(libc_32, libvndk_a_32.deps_all)
        self.assertIn(libc_32, libvndk_b_32.deps_all)
        self.assertIn(libc_32, libvndk_c_32.deps_all)
        self.assertIn(libc_32, libvndk_d_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_a_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_b_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_c_32.deps_all)
        self.assertIn(libc_32, libvndk_sp_d_32.deps_all)

        self.assertIn(libvndk_b_32, libvndk_a_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_a_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_b_32.deps_all)
        self.assertIn(libvndk_sp_b_32, libvndk_sp_a_32.deps_all)

        self.assertIn(libvndk_d_32, libvndk_c_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_c_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_d_32.deps_all)
        self.assertIn(libvndk_sp_d_32, libvndk_sp_c_32.deps_all)

        # 64-bit shared libraries
        self.assertIn(libc_64, libvndk_a_64.deps_all)
        self.assertIn(libc_64, libvndk_b_64.deps_all)
        self.assertIn(libc_64, libvndk_c_64.deps_all)
        self.assertIn(libc_64, libvndk_d_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_a_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_b_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_c_64.deps_all)
        self.assertIn(libc_64, libvndk_sp_d_64.deps_all)

        self.assertIn(libvndk_b_64, libvndk_a_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_a_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_b_64.deps_all)
        self.assertIn(libvndk_sp_b_64, libvndk_sp_a_64.deps_all)

        self.assertIn(libvndk_d_64, libvndk_c_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_c_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_d_64.deps_all)
        self.assertIn(libvndk_sp_d_64, libvndk_sp_c_64.deps_all)
示例#29
0
    def test_compute_sp_lib(self):
        # Create graph.
        gb = GraphBuilder()

        # LL-NDK (should be excluded from result)
        gb.add_multilib(PT_SYSTEM, 'libc')

        libEGL_32, libEGL_64 = \
                gb.add_multilib(PT_SYSTEM, 'libEGL',
                                dt_needed=['libc.so', 'libutils.so'])

        # LL-NDK dependencies
        gb.add_multilib(PT_SYSTEM, 'libutils',
                        dt_needed=['libc.so', 'libcutils.so'])

        # VNDK-SP used by both LL-NDK and SP-HAL
        gb.add_multilib(PT_SYSTEM, 'libsp_both_vs')

        # VNDK-SP used by LL-NDK
        gb.add_multilib(PT_SYSTEM, 'libcutils_dep', dt_needed=['libc.so'])
        gb.add_multilib(PT_SYSTEM, 'libcutils',
                        dt_needed=['libc.so', 'libcutils_dep.so',
                                   'libsp_both_vs.so'])

        # VNDK-SP used by SP-HAL
        gb.add_multilib(PT_SYSTEM, 'libhidlbase')
        gb.add_multilib(PT_SYSTEM, 'libhidlmemory',
                        dt_needed=['libhidlbase.so', 'libsp_both_vs.so'])

        # 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
        libEGL_chipset_32, libEGL_chipset_64 = \
                gb.add_multilib(PT_VENDOR, 'libEGL_chipset', extra_dir='egl',
                                dt_needed=['libc.so', 'libllvm_vendor.so',
                                           'libhidlmemory.so'])

        gb.resolve()

        # Add dlopen() dependencies from libEGL to libEGL_chipset.
        libEGL_32.add_dlopen_dep(libEGL_chipset_32)
        libEGL_64.add_dlopen_dep(libEGL_chipset_64)

        # 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_lib = gb.graph.compute_sp_lib(MockGenericRefs())

        self.assertEqual(2 * 1, len(sp_lib.sp_hal))
        self.assertEqual(2 * 2, len(sp_lib.sp_hal_dep))
        self.assertEqual(2 * 2, len(sp_lib.vndk_sp_hal))
        self.assertEqual(2 * 2, len(sp_lib.ll_ndk))
        self.assertEqual(2 * 3, len(sp_lib.ll_ndk_indirect))
        self.assertEqual(2 * 1, len(sp_lib.vndk_sp_both))

        sp_hal = self._get_paths_from_nodes(sp_lib.sp_hal)
        sp_hal_dep = self._get_paths_from_nodes(sp_lib.sp_hal_dep)
        vndk_sp_hal = self._get_paths_from_nodes(sp_lib.vndk_sp_hal)

        ll_ndk = self._get_paths_from_nodes(sp_lib.ll_ndk)
        ll_ndk_indirect = self._get_paths_from_nodes(sp_lib.ll_ndk_indirect)

        vndk_sp_both = self._get_paths_from_nodes(sp_lib.vndk_sp_both)

        for lib_dir in ('lib', 'lib64'):
            # VNDK-SP used by both LL-NDK and SP-HAL
            self.assertIn('/system/{}/libsp_both_vs.so'.format(lib_dir),
                          vndk_sp_both)

            # VNDK-SP used by LL-NDK
            self.assertIn('/system/{}/libcutils.so'.format(lib_dir),
                          ll_ndk_indirect)
            self.assertIn('/system/{}/libcutils_dep.so'.format(lib_dir),
                          ll_ndk_indirect)
            self.assertIn('/system/{}/libutils.so'.format(lib_dir),
                          ll_ndk_indirect)

            # VNDK-SP used by SP-HAL
            self.assertIn('/system/{}/libhidlbase.so'.format(lib_dir),
                          vndk_sp_hal)
            self.assertIn('/system/{}/libhidlmemory.so'.format(lib_dir),
                          vndk_sp_hal)

            # 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
            self.assertIn('/vendor/{}/egl/libEGL_chipset.so'.format(lib_dir),
                          sp_hal)

            # LL-NDK
            self.assertIn('/system/{}/libEGL.so'.format(lib_dir), ll_ndk)
            self.assertIn('/system/{}/libc.so'.format(lib_dir), ll_ndk)

            # LL-NDK must not in sp_hal, sp_hal_dep, and vndk_sp_hal.
            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, vndk_sp_hal)
            self.assertNotIn(libc_path, ll_ndk_indirect)
示例#30
0
    def _create_normal_graph(self):
        gb = GraphBuilder()

        gb.add_multilib(PT_SYSTEM, 'libdl',
                        exported_symbols={'dlclose', 'dlopen', 'dlsym'})

        gb.add_multilib(PT_SYSTEM, 'libm', exported_symbols={'cos', 'sin'})

        gb.add_multilib(PT_SYSTEM, 'libc', dt_needed=['libdl.so', 'libm.so'],
                        exported_symbols={'fclose', 'fopen', 'fread'},
                        imported_symbols={'dlclose', 'dlopen', 'cos', 'sin'})

        gb.add_multilib(PT_SYSTEM, 'libRS', dt_needed=['libdl.so'],
                        exported_symbols={'rsContextCreate'},
                        imported_symbols={'dlclose', 'dlopen', 'dlsym'})

        gb.add_multilib(PT_SYSTEM, 'libcutils',
                        dt_needed=['libc.so', 'libdl.so'],
                        imported_symbols={'dlclose', 'dlopen', 'fclose',
                                          'fopen'})

        gb.add_multilib(PT_VENDOR, 'libEGL',
                        dt_needed=['libc.so', 'libcutils.so', 'libdl.so'],
                        exported_symbols={'eglGetDisplay'},
                        imported_symbols={'fclose', 'fopen'})

        gb.resolve()
        return gb
示例#31
0
    def test_compute_predefined_sp_hal(self):
        gb = GraphBuilder()

        # HIDL SP-HAL implementation.
        gb.add_multilib(PT_SYSTEM, 'gralloc.default', extra_dir='hw')
        gb.add_multilib(PT_SYSTEM, 'gralloc.chipset', extra_dir='hw')
        gb.add_multilib(PT_SYSTEM, '[email protected]',
                        extra_dir='hw')

        # NDK loader libraries should not be considered as SP-HALs.
        gb.add_multilib(PT_SYSTEM, 'libvulkan')
        gb.add_multilib(PT_SYSTEM, 'libEGL')
        gb.add_multilib(PT_SYSTEM, 'libGLESv1_CM')
        gb.add_multilib(PT_SYSTEM, 'libGLESv2')
        gb.add_multilib(PT_SYSTEM, 'libGLESv3')

        # 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')

        # Renderscript implementation.
        gb.add_multilib(PT_VENDOR, 'libRSDriver_chipset')
        gb.add_multilib(PT_VENDOR, 'libPVRRS')

        # Vulkan implementation.
        gb.add_multilib(PT_VENDOR, 'vulkan.chipset', extra_dir='hw')

        # Some un-related libraries.
        gb.add_multilib(PT_SYSTEM, 'libfoo')
        gb.add_multilib(PT_VENDOR, 'libfoo')

        gb.resolve()

        # Compute SP-HAL.
        sp_hals = set(lib.path for lib in gb.graph.compute_predefined_sp_hal())

        for lib in ('lib', 'lib64'):
            # Check HIDL SP-HAL implementation.
            self.assertIn('/system/' + lib + '/hw/gralloc.default.so', sp_hals)
            self.assertIn('/system/' + lib + '/hw/gralloc.chipset.so', sp_hals)
            self.assertIn('/system/' + lib + '/hw/'
                          '*****@*****.**',
                          sp_hals)


            # Check that NDK loaders are not SP-HALs.
            self.assertNotIn('/system/' + lib + '/libvulkan.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libEGL.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv1_CM.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv2.so', sp_hals)
            self.assertNotIn('/system/' + lib + '/libGLESv3.so', sp_hals)

            # 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',
                          sp_hals)
            self.assertIn('/vendor/' + lib + '/egl/libGLESv3_chipset.so',
                          sp_hals)

            # Check that Renderscript implementations are SP-HALs.
            self.assertIn('/vendor/' + lib + '/libRSDriver_chipset.so', sp_hals)
            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)

            # Check that vulkan implementation are SP-HALs.
            self.assertIn('/vendor/' + lib + '/libPVRRS.so', sp_hals)

            # Check that un-related libraries are not SP-HALs.
            self.assertNotIn('/system/' + lib + '/libfoo.so', sp_hals)
            self.assertNotIn('/vendor/' + lib + '/libfoo.so', sp_hals)