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