Implement LOCAL_TEST_DATA to ship data with tests

This can be used to ship source data as test artifacts next to native
tests. It works for both local builds and the test bundles using
package_modules.mk.

You just specify a file list relative to the local directory, and those
files will be copied next to the executable under
/data/nativetest*/<module>/...:

  LOCAL_MODULE := mytest
  LOCAL_TEST_DATA := data/file1 file2

  /data/nativetest/mytest/mytest
  /data/nativetest/mytest/data/file1
  /data/nativetest/mytest/file2

If the data is in another directory, you may also specify a different
prefix for the source files:

  LOCAL_TEST_DATA := external/skia:resources/f.xml

  /data/nativetest/skia_test/resources/f.xml

And there's a new convenience macro to find a list of files in this
format:

  LOCAL_TEST_DATA := $(call find-test-data-in-subdirs,external/skia,"*.xml",resources)

I'll expand this to native benchmarks and fuzz tests in a later change,
since they don't have their own module classes yet.

Bug: 30564705
Test: m -j minikin_tests; ls $OUT/data/nativetest*/minikin_tests
Test: m -j continuous_native_tests dist; zipinfo -1 out/dist/*continuous_native_tests*.zip
Change-Id: Ic76a7b62e7f567f259c4ab1510ee97d26600ba9a
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 0cdaabd..68ac08b 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -461,6 +461,33 @@
 endif  # LOCAL_COMPATIBILITY_SUITE
 
 ###########################################################
+## Test Data
+###########################################################
+my_test_data_pairs :=
+my_installed_test_data :=
+
+ifneq ($(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ifneq ($(strip $(LOCAL_TEST_DATA)),)
+ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
+
+my_test_data_pairs := $(strip $(foreach td,$(LOCAL_TEST_DATA), \
+    $(eval _file := $(call word-colon,2,$(td))) \
+    $(if $(_file), \
+      $(eval _base := $(call word-colon,1,$(td))), \
+      $(eval _base := $(LOCAL_PATH)) \
+        $(eval _file := $(call word-colon,1,$(td)))) \
+    $(if $(findstring ..,$(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include '..': $(_file))) \
+    $(if $(filter /%,$(_base) $(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include absolute paths: $(_base) $(_file))) \
+    $(call append-path,$(_base),$(_file)):$(call append-path,$(my_module_path),$(_file))))
+
+my_installed_test_data := $(call copy-many-files,$(my_test_data_pairs))
+$(LOCAL_INSTALLED_MODULE): $(my_installed_test_data)
+
+endif
+endif
+endif
+
+###########################################################
 ## Register with ALL_MODULES
 ###########################################################
 
@@ -481,11 +508,12 @@
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 ALL_MODULES.$(my_register_name).INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).INSTALLED) \
-    $(LOCAL_INSTALLED_MODULE) $(my_init_rc_installed) $(my_installed_symlinks))
+    $(LOCAL_INSTALLED_MODULE) $(my_init_rc_installed) $(my_installed_symlinks) \
+    $(my_installed_test_data))
 ALL_MODULES.$(my_register_name).BUILT_INSTALLED := \
     $(strip $(ALL_MODULES.$(my_register_name).BUILT_INSTALLED) \
     $(LOCAL_BUILT_MODULE):$(LOCAL_INSTALLED_MODULE) \
-    $(my_init_rc_pairs))
+    $(my_init_rc_pairs) $(my_test_data_pairs))
 endif
 ifdef LOCAL_PICKUP_FILES
 # Files or directories ready to pick up by the build system
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index 07f7841..c0343a0 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -209,6 +209,7 @@
 LOCAL_STATIC_LIBRARIES:=
 LOCAL_STRIP_MODULE:=
 LOCAL_SYSTEM_SHARED_LIBRARIES:=none
+LOCAL_TEST_DATA:=
 LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
 LOCAL_TIDY:=
 LOCAL_TIDY_CHECKS:=
diff --git a/core/definitions.mk b/core/definitions.mk
index 698f52c..969260b 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -469,6 +469,20 @@
 endef
 
 ###########################################################
+## Find test data in a form required by LOCAL_TEST_DATA
+## $(1): the base dir, relative to the root of the source tree.
+## $(3): the file name pattern to be passed to find as "-name"
+## $(2): a list of subdirs of the base dir
+###########################################################
+
+define find-test-data-in-subdirs
+$(foreach f,$(sort $(patsubst ./%,%, \
+  $(shell cd $(1) ; \
+          find -L $(3) -type f -and -name $(2) -and -not -name ".*") \
+)),$(1):$(f))
+endef
+
+###########################################################
 ## Function we can evaluate to introduce a dynamic dependency
 ###########################################################