vndk-def: Fix sp-hal and vndk-stable computation.
This commit fixes the computation algorithm for sp-hal and vndk-stable.
Before this commit, vndk-stable are determined from a pre-defined set
and sp-hal might include AOSP libraries. After this commit, we are
adding SP-HAL dependencies to VNDK-stable if the dependency is an AOSP
library.
Test: ./tests/test_elf_linker.py
Change-Id: I7df3374ff49ff33826f496c0fabcb3749efd4fb2
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..60fdb4d 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.
@@ -341,7 +341,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.
@@ -379,38 +379,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/vndk_definition_tool.py b/vndk/tools/definition-tool/vndk_definition_tool.py
index bc85863..8f42b8f 100755
--- a/vndk/tools/definition-tool/vndk_definition_tool.py
+++ b/vndk/tools/definition-tool/vndk_definition_tool.py
@@ -917,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."""
@@ -975,13 +964,9 @@
'^.*/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 = (
@@ -1000,11 +985,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):
@@ -1771,14 +1784,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.
@@ -1804,7 +1819,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:
@@ -1812,8 +1827,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)
@@ -1983,26 +2001,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
@@ -2022,7 +2056,7 @@
register_subcmd(VNDKCapCommand())
register_subcmd(DepsCommand())
register_subcmd(DepsClosureCommand())
- register_subcmd(SpHalCommand())
+ register_subcmd(SpLibCommand())
register_subcmd(VNDKStableCommand())
args = parser.parse_args()