Merge qt-r1-dev-plus-aosp-without-vendor (5817612) into stage-aosp-master
Bug: 135460123
Change-Id: Ia07db5c8afeed7fe22a2b18d867a38390f910a81
Merged-In: Ibbd540dbb5baee46360d3fe9469212cfd8f550ba
diff --git a/Android.bp b/Android.bp
index 927e227..dd84737 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,11 @@
"VtsHalHidlTargetTestBase",
"libhidl-gen-utils",
],
+
+ header_libs: [
+ "libhidl_gtest_helpers",
+ ],
+
group_static_libs: true,
// Lists all system dependencies that can be expected on the device.
@@ -33,8 +38,6 @@
"libcutils",
"liblog",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"libutils",
],
cflags: [
diff --git a/atrace/1.0/default/Android.bp b/atrace/1.0/default/Android.bp
index bcaf064..4bbbdb3 100644
--- a/atrace/1.0/default/Android.bp
+++ b/atrace/1.0/default/Android.bp
@@ -29,7 +29,6 @@
"libbase",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.atrace@1.0",
],
}
diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index b57a1ae..236f1fd 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -34,11 +34,9 @@
libcutils \
libbinder \
libhidlbase \
- libhidltransport \
liblog \
libutils \
libhardware \
- libhwbinder \
android.hardware.audio@2.0 \
android.hardware.audio@4.0 \
android.hardware.audio@5.0 \
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index a1af3c4..000ce18 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -24,7 +24,6 @@
"libfmq",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.audio.common-util",
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index f23a463..653b30c 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -28,7 +28,6 @@
"libfmq",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.audio.common-util",
diff --git a/authsecret/1.0/default/Android.bp b/authsecret/1.0/default/Android.bp
index 5c3234f..b6ea3c4 100644
--- a/authsecret/1.0/default/Android.bp
+++ b/authsecret/1.0/default/Android.bp
@@ -13,7 +13,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.authsecret@1.0",
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
index 0e074dd..314830b 100644
--- a/automotive/audiocontrol/1.0/default/Android.bp
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -26,7 +26,6 @@
shared_libs: [
"android.hardware.automotive.audiocontrol@1.0",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
index 7286478..69bb721 100644
--- a/automotive/evs/1.0/default/Android.bp
+++ b/automotive/evs/1.0/default/Android.bp
@@ -18,7 +18,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libui",
"libutils",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index a11d452..3fd0539 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -16,7 +16,6 @@
name: "vhal_v2_0_defaults",
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.automotive.vehicle@2.0",
diff --git a/biometrics/fingerprint/2.1/default/Android.bp b/biometrics/fingerprint/2.1/default/Android.bp
index b12ce61..497fa3f 100644
--- a/biometrics/fingerprint/2.1/default/Android.bp
+++ b/biometrics/fingerprint/2.1/default/Android.bp
@@ -13,7 +13,6 @@
"libcutils",
"liblog",
"libhidlbase",
- "libhidltransport",
"libhardware",
"libutils",
"android.hardware.biometrics.fingerprint@2.1",
diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp
index f4b1e7b..f66c25e 100644
--- a/bluetooth/1.0/default/Android.bp
+++ b/bluetooth/1.0/default/Android.bp
@@ -29,7 +29,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -130,7 +129,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.bluetooth@1.0",
],
}
diff --git a/bluetooth/a2dp/1.0/default/Android.bp b/bluetooth/a2dp/1.0/default/Android.bp
index 8e6f32d..5264899 100644
--- a/bluetooth/a2dp/1.0/default/Android.bp
+++ b/bluetooth/a2dp/1.0/default/Android.bp
@@ -1,5 +1,5 @@
cc_library_shared {
- name: "android.hardware.bluetooth.a2dp@1.0-impl",
+ name: "android.hardware.bluetooth.a2dp@1.0-impl.mock",
relative_install_path: "hw",
vendor: true,
srcs: [
@@ -7,7 +7,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.bluetooth.a2dp@1.0",
],
diff --git a/bluetooth/audio/2.0/default/Android.bp b/bluetooth/audio/2.0/default/Android.bp
index 1dfc05d..0db0028 100644
--- a/bluetooth/audio/2.0/default/Android.bp
+++ b/bluetooth/audio/2.0/default/Android.bp
@@ -19,7 +19,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -41,7 +40,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index 397c56d..fdf7a1e 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -9,7 +9,6 @@
shared_libs: [
"liblog",
"libhidlbase",
- "libhidltransport",
"libhardware",
"libutils",
"android.hardware.boot@1.0",
@@ -29,7 +28,6 @@
"liblog",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.boot@1.0",
],
diff --git a/broadcastradio/1.0/default/Android.bp b/broadcastradio/1.0/default/Android.bp
index f961dfd..2c96e2a 100644
--- a/broadcastradio/1.0/default/Android.bp
+++ b/broadcastradio/1.0/default/Android.bp
@@ -31,7 +31,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
"libhardware",
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/1.1/default/Android.bp
index 52fb45b..3659cb9 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/1.1/default/Android.bp
@@ -41,7 +41,6 @@
"android.hardware.broadcastradio@1.1",
"libbase",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 840c4b8..83eedb1 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -42,7 +42,6 @@
"android.hardware.broadcastradio@2.0",
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
],
}
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index aa3b941..97d0b5f 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -8,8 +8,6 @@
shared_libs: [
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
- "libhwbinder",
"libutils",
"android.hardware.camera.device@1.0",
"android.hardware.camera.common@1.0",
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index edb008e..e4d9e85 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -7,7 +7,6 @@
"convert.cpp"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"android.hardware.camera.device@3.2",
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
index 39d379d..d964f3d 100644
--- a/camera/device/3.3/default/Android.bp
+++ b/camera/device/3.3/default/Android.bp
@@ -7,7 +7,6 @@
"convert.cpp"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"camera.device@3.2-impl",
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index c22b13c..71a9e77 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -38,7 +38,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"camera.device@3.2-impl",
@@ -75,7 +74,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"camera.device@3.2-impl",
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 26b3b67..43362fd 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -37,7 +37,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"camera.device@3.2-impl",
@@ -71,7 +70,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"camera.device@3.2-impl",
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index cb78fcb..95e27fd 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -24,7 +24,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -63,7 +62,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libtinyxml2",
"libutils",
@@ -108,7 +106,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libtinyxml2",
"libutils",
@@ -146,7 +143,6 @@
"libcamera_metadata",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -211,7 +207,6 @@
"android.hardware.camera.provider@2.4",
"libbinder",
"libhidlbase",
- "libhidltransport",
"liblog",
"libtinyxml2",
"libutils",
diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp
index cd1caeb..4563362 100644
--- a/camera/provider/2.5/default/Android.bp
+++ b/camera/provider/2.5/default/Android.bp
@@ -24,7 +24,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -64,7 +63,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libtinyxml2",
"libutils",
@@ -103,7 +101,6 @@
"libcamera_metadata",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -170,7 +167,6 @@
"android.hardware.graphics.mapper@2.0",
"libbinder",
"libhidlbase",
- "libhidltransport",
"liblog",
"libtinyxml2",
"libutils",
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index aa080f4..f9977ff 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -21,7 +21,6 @@
"libbinder",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libstagefright_foundation",
"libutils",
diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp
index 68a49cf..66a1eb8 100644
--- a/cas/1.1/default/Android.bp
+++ b/cas/1.1/default/Android.bp
@@ -22,7 +22,6 @@
"libbinder",
"libhidlbase",
"libhidlmemory",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 6e1bc8f..be8d7ca 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -426,7 +426,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.thermal</name>
- <version>1.0-1</version>
+ <version>1.0</version>
<version>2.0</version>
<interface>
<name>IThermal</name>
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
index 104e15e..e7edc34 100644
--- a/configstore/1.1/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -17,7 +17,6 @@
LOCAL_SHARED_LIBRARIES := \
libhidlbase \
- libhidltransport \
libbase \
libhwminijail \
liblog \
diff --git a/confirmationui/1.0/default/Android.bp b/confirmationui/1.0/default/Android.bp
index 10018e8..ecba064 100644
--- a/confirmationui/1.0/default/Android.bp
+++ b/confirmationui/1.0/default/Android.bp
@@ -36,7 +36,6 @@
"libcrypto",
"libbase",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/contexthub/1.0/default/Android.bp b/contexthub/1.0/default/Android.bp
index d1db6a6..8384037 100644
--- a/contexthub/1.0/default/Android.bp
+++ b/contexthub/1.0/default/Android.bp
@@ -28,7 +28,6 @@
"libcutils",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.contexthub@1.0",
],
}
@@ -47,7 +46,6 @@
"libdl",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.contexthub@1.0",
diff --git a/current.txt b/current.txt
index fbb9752..b7383ea 100644
--- a/current.txt
+++ b/current.txt
@@ -574,6 +574,7 @@
# ABI preserving changes to HALs during Android R
b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
ad431c8de51c07934a068e3043d8dd0537ac4d3158627706628b123f42df48dc android.hardware.neuralnetworks@1.0::IPreparedModel
+fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
aafcc10cf04ab247e86d4582586c71c6b4c2b8c479241ffa7fe37deb659fc942 android.hardware.neuralnetworks@1.2::IPreparedModel
1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index d66f377..9016dc3 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -59,7 +59,6 @@
libcutils \
libhidlbase \
libhidlmemory \
- libhidltransport \
liblog \
libstagefright_foundation \
libutils \
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
index 28db567..1b5a975 100644
--- a/drm/1.0/default/common_default_service.mk
+++ b/drm/1.0/default/common_default_service.mk
@@ -21,7 +21,6 @@
android.hardware.drm@1.0 \
android.hidl.memory@1.0 \
libhidlbase \
- libhidltransport \
libhardware \
liblog \
libutils \
diff --git a/dumpstate/1.0/default/Android.bp b/dumpstate/1.0/default/Android.bp
index 3ca19e8..6b02715 100644
--- a/dumpstate/1.0/default/Android.bp
+++ b/dumpstate/1.0/default/Android.bp
@@ -1,5 +1,5 @@
cc_binary {
- name: "android.hardware.dumpstate@1.0-service",
+ name: "android.hardware.dumpstate@1.0-service.example",
init_rc: ["android.hardware.dumpstate@1.0-service.rc"],
relative_install_path: "hw",
vendor: true,
@@ -18,7 +18,6 @@
"libcutils",
"libdumpstateutil",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
index 062a291..03298dc 100644
--- a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
+++ b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
@@ -1,4 +1,4 @@
-service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service
+service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service.example
class hal
user system
group system
diff --git a/fastboot/1.0/default/Android.bp b/fastboot/1.0/default/Android.bp
index fde7efa..f7b3635 100644
--- a/fastboot/1.0/default/Android.bp
+++ b/fastboot/1.0/default/Android.bp
@@ -23,7 +23,6 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
"libcutils",
"android.hardware.fastboot@1.0",
diff --git a/gatekeeper/1.0/default/Android.bp b/gatekeeper/1.0/default/Android.bp
index ae3b91c..2be4f4d 100644
--- a/gatekeeper/1.0/default/Android.bp
+++ b/gatekeeper/1.0/default/Android.bp
@@ -10,7 +10,6 @@
"android.hardware.gatekeeper@1.0",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
],
@@ -30,7 +29,6 @@
"android.hardware.gatekeeper@1.0",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
],
diff --git a/gatekeeper/1.0/software/Android.bp b/gatekeeper/1.0/software/Android.bp
index 148c989..24c81f6 100644
--- a/gatekeeper/1.0/software/Android.bp
+++ b/gatekeeper/1.0/software/Android.bp
@@ -15,7 +15,6 @@
"libbase",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
"libcrypto",
diff --git a/gnss/1.0/default/Android.bp b/gnss/1.0/default/Android.bp
index ca495e6..57d8903 100644
--- a/gnss/1.0/default/Android.bp
+++ b/gnss/1.0/default/Android.bp
@@ -22,7 +22,6 @@
shared_libs: [
"liblog",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.gnss@1.0",
"libhardware",
@@ -47,7 +46,6 @@
"libhardware",
"libbinder",
"libhidlbase",
- "libhidltransport",
"android.hardware.gnss@1.0",
],
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 8c3aac4..95bd7f3 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -12,7 +12,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
"android.hardware.gnss@1.1",
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 0fcd764..3ba89da 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -33,7 +33,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"liblog",
"android.hardware.gnss@2.0",
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 9980ae0..59229b0 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -13,7 +13,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
@@ -31,7 +30,6 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 63accff..6157719 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -16,7 +16,6 @@
"libfmq",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libsync",
"libutils",
@@ -39,7 +38,6 @@
"android.hardware.graphics.composer@2.1",
"libbinder",
"libhidlbase",
- "libhidltransport",
"liblog",
"libsync",
"libutils",
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
index 7dedf61..4916557 100644
--- a/graphics/composer/2.2/default/Android.mk
+++ b/graphics/composer/2.2/default/Android.mk
@@ -19,7 +19,6 @@
libfmq \
libhardware \
libhidlbase \
- libhidltransport \
libhwc2on1adapter \
libhwc2onfbadapter \
liblog \
diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp
index 07afd6c..59b9436 100644
--- a/graphics/composer/2.3/default/Android.bp
+++ b/graphics/composer/2.3/default/Android.bp
@@ -36,7 +36,6 @@
"libfmq",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libhwc2on1adapter",
"libhwc2onfbadapter",
"liblog",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 2766638..e421889 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -23,7 +23,6 @@
shared_libs: [
"libfmq",
"libhidlbase",
- "libhidltransport",
"libsync",
],
static_libs: [
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 8874799..4f64184 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -28,7 +28,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libsync",
"libutils",
diff --git a/graphics/mapper/2.1/default/Android.bp b/graphics/mapper/2.1/default/Android.bp
index aa204a0..2ea7f94 100644
--- a/graphics/mapper/2.1/default/Android.bp
+++ b/graphics/mapper/2.1/default/Android.bp
@@ -29,7 +29,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"liblog",
"libsync",
"libutils",
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 8fbb8c3..049e393 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -12,7 +12,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.health@1.0",
],
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
index 199ab41..bbf37af 100644
--- a/health/1.0/default/Android.mk
+++ b/health/1.0/default/Android.mk
@@ -13,7 +13,6 @@
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhidlbase \
- libhidltransport \
liblog \
libutils \
android.hardware.health@1.0 \
@@ -39,7 +38,6 @@
libbase \
libutils \
libhidlbase \
- libhidltransport \
android.hardware.health@1.0 \
include $(BUILD_EXECUTABLE)
diff --git a/health/2.0/README.md b/health/2.0/README.md
index 58ea9e3..4ecfb9a 100644
--- a/health/2.0/README.md
+++ b/health/2.0/README.md
@@ -44,7 +44,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.health@2.0",
],
diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp
index a85a704..1c455d3 100644
--- a/health/2.0/default/Android.bp
+++ b/health/2.0/default/Android.bp
@@ -10,8 +10,6 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
"libcutils",
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
index 4723443..3156dfe 100644
--- a/health/storage/1.0/default/Android.bp
+++ b/health/storage/1.0/default/Android.bp
@@ -33,7 +33,6 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.health.storage@1.0",
],
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index b18e36f..87502f8 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -21,7 +21,6 @@
static_libs: ["android.hardware.health.storage@1.0"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
],
test_suites: ["general-tests"],
}
diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp
index ceb2aca..3379a76 100644
--- a/input/classifier/1.0/default/Android.bp
+++ b/input/classifier/1.0/default/Android.bp
@@ -11,7 +11,6 @@
shared_libs: [
"android.hardware.input.classifier@1.0",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
],
diff --git a/ir/1.0/default/Android.bp b/ir/1.0/default/Android.bp
index 2b15387..80e0f3c 100644
--- a/ir/1.0/default/Android.bp
+++ b/ir/1.0/default/Android.bp
@@ -20,7 +20,6 @@
srcs: ["ConsumerIr.cpp"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libhardware",
"liblog",
"libutils",
@@ -40,7 +39,6 @@
"liblog",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.ir@1.0",
],
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
index 9e7d04a..208cb66 100644
--- a/keymaster/3.0/default/Android.mk
+++ b/keymaster/3.0/default/Android.mk
@@ -15,7 +15,6 @@
libpuresoftkeymasterdevice \
libkeymaster3device \
libhidlbase \
- libhidltransport \
libutils \
libhardware \
android.hardware.keymaster@3.0
@@ -38,7 +37,6 @@
libutils \
libhardware \
libhidlbase \
- libhidltransport \
android.hardware.keymaster@3.0
include $(BUILD_EXECUTABLE)
diff --git a/keymaster/4.0/default/Android.bp b/keymaster/4.0/default/Android.bp
index 0cede50..f9e3986 100644
--- a/keymaster/4.0/default/Android.bp
+++ b/keymaster/4.0/default/Android.bp
@@ -28,7 +28,6 @@
"libcutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libkeymaster4",
"liblog",
"libutils",
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index ccd1b56..2f40282 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -39,7 +39,6 @@
"libcrypto",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
]
}
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 293c50c..9e6cce7 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -4339,75 +4339,61 @@
*
* This test checks that if rollback protection is implemented, DeleteKey invalidates a formerly
* valid key blob.
- *
- * TODO(swillden): Update to incorporate changes in rollback resistance semantics.
*/
TEST_F(KeyDeletionTest, DeleteKey) {
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)));
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
// Delete must work if rollback protection is implemented
- AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
- bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- if (rollback_protected) {
ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
- } else {
- auto delete_result = DeleteKey(true /* keep key blob */);
- ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
- }
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_out_params;
-
- if (rollback_protected) {
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN, key_blob_,
AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
&begin_out_params, &op_handle_));
- } else {
- EXPECT_EQ(ErrorCode::OK,
- Begin(KeyPurpose::SIGN, key_blob_,
- AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
- &begin_out_params, &op_handle_));
+ AbortIfNeeded();
+ key_blob_ = HidlBuf();
}
- AbortIfNeeded();
- key_blob_ = HidlBuf();
}
/**
* KeyDeletionTest.DeleteInvalidKey
*
- * This test checks that the HAL excepts invalid key blobs.
- *
- * TODO(swillden): Update to incorporate changes in rollback resistance semantics.
+ * This test checks that the HAL excepts invalid key blobs..
*/
TEST_F(KeyDeletionTest, DeleteInvalidKey) {
// Generate key just to check if rollback protection is implemented
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)));
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
// Delete must work if rollback protection is implemented
- AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
- bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- // Delete the key we don't care about the result at this point.
- DeleteKey();
+ // Delete the key we don't care about the result at this point.
+ DeleteKey();
- // Now create an invalid key blob and delete it.
- key_blob_ = HidlBuf("just some garbage data which is not a valid key blob");
+ // Now create an invalid key blob and delete it.
+ key_blob_ = HidlBuf("just some garbage data which is not a valid key blob");
- if (rollback_protected) {
ASSERT_EQ(ErrorCode::OK, DeleteKey());
- } else {
- auto delete_result = DeleteKey();
- ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
}
}
@@ -4421,39 +4407,34 @@
* device has been wiped manually (e.g., fastboot flashall -w), and new FBE/FDE keys have
* been provisioned. Use this test only on dedicated testing devices that have no valuable
* credentials stored in Keystore/Keymaster.
- *
- * TODO(swillden): Update to incorporate changes in rollback resistance semantics.
*/
TEST_F(KeyDeletionTest, DeleteAllKeys) {
if (!arm_deleteAllKeys) return;
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .RsaSigningKey(2048, 65537)
- .Digest(Digest::NONE)
- .Padding(PaddingMode::NONE)
- .Authorization(TAG_NO_AUTH_REQUIRED)));
+ auto error = GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Digest(Digest::NONE)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .Authorization(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
// Delete must work if rollback protection is implemented
- AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
- bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+ if (error == ErrorCode::OK) {
+ AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+ ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_out_params;
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
- if (rollback_protected) {
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
Begin(KeyPurpose::SIGN, key_blob_,
AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
&begin_out_params, &op_handle_));
- } else {
- EXPECT_EQ(ErrorCode::OK,
- Begin(KeyPurpose::SIGN, key_blob_,
- AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
- &begin_out_params, &op_handle_));
+ AbortIfNeeded();
+ key_blob_ = HidlBuf();
}
- AbortIfNeeded();
- key_blob_ = HidlBuf();
}
using UpgradeKeyTest = KeymasterHidlTest;
diff --git a/light/2.0/default/Android.bp b/light/2.0/default/Android.bp
index 72cc873..ed48825 100644
--- a/light/2.0/default/Android.bp
+++ b/light/2.0/default/Android.bp
@@ -23,7 +23,6 @@
"libbase",
"liblog",
"libhidlbase",
- "libhidltransport",
"libhardware",
"libutils",
"android.hardware.light@2.0",
@@ -44,7 +43,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.light@2.0",
],
}
diff --git a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
index 13290d9..6fcecd2 100644
--- a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
+++ b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
@@ -16,11 +16,13 @@
#define LOG_TAG "light_hidl_hal_test"
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
#include <android-base/logging.h>
#include <android/hardware/light/2.0/ILight.h>
#include <android/hardware/light/2.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
#include <unistd.h>
#include <set>
@@ -73,25 +75,10 @@
Type::WIFI
};
-// Test environment for Light HIDL HAL.
-class LightHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
- public:
- // get the test environment singleton
- static LightHidlEnvironment* Instance() {
- static LightHidlEnvironment* instance = new LightHidlEnvironment;
- return instance;
- }
-
- virtual void registerTestServices() override { registerTestService<ILight>(); }
- private:
- LightHidlEnvironment() {}
-};
-
-class LightHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-public:
+class LightHidlTest : public testing::TestWithParam<std::string> {
+ public:
virtual void SetUp() override {
- light = ::testing::VtsHalHidlTargetTestBase::getService<ILight>(
- LightHidlEnvironment::Instance()->getServiceName<ILight>());
+ light = ILight::getService(GetParam());
ASSERT_NE(light, nullptr);
LOG(INFO) << "Test is remote " << light->isRemote();
@@ -120,13 +107,12 @@
EXPECT_EQ(Status::SUCCESS, static_cast<Status>(ret));
}
}
-
};
/**
* Ensure all lights which are reported as supported work.
*/
-TEST_F(LightHidlTest, TestSupported) {
+TEST_P(LightHidlTest, TestSupported) {
for (const Type& type: supportedTypes) {
Return<Status> ret = light->setLight(type, kWhite);
EXPECT_OK(ret);
@@ -137,7 +123,7 @@
/**
* Ensure BRIGHTNESS_NOT_SUPPORTED is returned if LOW_PERSISTANCE is not supported.
*/
-TEST_F(LightHidlTest, TestLowPersistance) {
+TEST_P(LightHidlTest, TestLowPersistance) {
for (const Type& type: supportedTypes) {
Return<Status> ret = light->setLight(type, kLowPersistance);
EXPECT_OK(ret);
@@ -151,7 +137,7 @@
/**
* Ensure lights which are not supported return LIGHT_NOT_SUPPORTED
*/
-TEST_F(LightHidlTest, TestUnsupported) {
+TEST_P(LightHidlTest, TestUnsupported) {
std::set<Type> unsupportedTypes = kAllTypes;
for (const Type& type: supportedTypes) {
unsupportedTypes.erase(type);
@@ -164,11 +150,7 @@
}
}
-int main(int argc, char **argv) {
- ::testing::AddGlobalTestEnvironment(LightHidlEnvironment::Instance());
- ::testing::InitGoogleTest(&argc, argv);
- LightHidlEnvironment::Instance()->init(&argc, argv);
- int status = RUN_ALL_TESTS();
- LOG(INFO) << "Test result = " << status;
- return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, LightHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(ILight::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/light/utils/Android.bp b/light/utils/Android.bp
index ebcbfa2..4c287e4 100644
--- a/light/utils/Android.bp
+++ b/light/utils/Android.bp
@@ -24,7 +24,6 @@
"android.hardware.light@2.0",
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
],
}
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 5a79e55..cdc52fb 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -29,21 +29,6 @@
"android.hidl.memory@1.0",
"android.hardware.media.omx@1.0",
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
- ],
- export_static_lib_headers: [
- "android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
- "android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
],
}
@@ -55,12 +40,7 @@
static_libs: [
"VtsHalMediaOmxV1_0CommonUtil",
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.allocator@3.0",
- "android.hardware.graphics.common@1.0",
- "android.hardware.graphics.common@1.1",
- "android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
- "android.hardware.graphics.mapper@3.0",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.common@1.0",
"android.hardware.media.omx@1.0",
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 8d4c022..f299e36 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -22,11 +22,8 @@
#include <android-base/logging.h>
#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
@@ -34,9 +31,7 @@
#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMapper.h>
#include <android/hidl/memory/1.0/IMemory.h>
-
-#include <atomic>
-#include <variant>
+#include <cutils/atomic.h>
using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
@@ -200,104 +195,67 @@
BufferInfo* buffer, uint32_t nFrameWidth,
uint32_t nFrameHeight, int32_t* nStride,
int format) {
- struct AllocatorV2 : public GrallocV2 {
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
- AllocatorV2(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
- : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
- AllocatorV2() = default;
- };
- struct AllocatorV3 : public GrallocV3 {
- sp<IAllocator> mAllocator;
- sp<IMapper> mMapper;
- AllocatorV3(sp<IAllocator>&& allocator, sp<IMapper>&& mapper)
- : mAllocator{std::move(allocator)}, mMapper{std::move(mapper)} {}
- AllocatorV3() = default;
- };
- std::variant<AllocatorV2, AllocatorV3> grallocVar;
+ android::hardware::media::omx::V1_0::Status status;
+ sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator =
+ android::hardware::graphics::allocator::V2_0::IAllocator::getService();
+ ASSERT_NE(nullptr, allocator.get());
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2{};
- sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3{};
- sp<android::hardware::graphics::allocator::V2_0::IAllocator> allocator2{};
- sp<android::hardware::graphics::allocator::V3_0::IAllocator> allocator3 =
- android::hardware::graphics::allocator::V3_0::IAllocator::getService();
- if (allocator3) {
- mapper3 =
- android::hardware::graphics::mapper::V3_0::IMapper::getService();
- ASSERT_NE(nullptr, mapper3.get());
- grallocVar.emplace<AllocatorV3>(std::move(allocator3), std::move(mapper3));
- } else {
- allocator2 =
- android::hardware::graphics::allocator::V2_0::IAllocator::getService();
- ASSERT_NE(nullptr, allocator2.get());
- mapper2 =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- ASSERT_NE(nullptr, allocator2.get());
- grallocVar.emplace<AllocatorV2>(std::move(allocator2), std::move(mapper2));
- }
+ sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
+ android::hardware::graphics::mapper::V2_0::IMapper::getService();
+ ASSERT_NE(mapper.get(), nullptr);
- android::hardware::media::omx::V1_0::Status status{};
- uint64_t usage{};
- ASSERT_TRUE(omxNode->getGraphicBufferUsage(
+ android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo
+ descriptorInfo;
+ uint32_t usage;
+
+ descriptorInfo.width = nFrameWidth;
+ descriptorInfo.height = nFrameHeight;
+ descriptorInfo.layerCount = 1;
+ descriptorInfo.format = static_cast<PixelFormat>(format);
+ descriptorInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN);
+ omxNode->getGraphicBufferUsage(
portIndex,
[&status, &usage](android::hardware::media::omx::V1_0::Status _s,
uint32_t _n1) {
status = _s;
usage = _n1;
- }).isOk());
- ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+ });
+ if (status == android::hardware::media::omx::V1_0::Status::OK) {
+ descriptorInfo.usage |= usage;
+ }
- static std::atomic_int32_t bufferIdCounter{0};
+ ::android::hardware::hidl_vec<uint32_t> descriptor;
+ android::hardware::graphics::mapper::V2_0::Error error;
+ mapper->createDescriptor(
+ descriptorInfo, [&error, &descriptor](
+ android::hardware::graphics::mapper::V2_0::Error _s,
+ ::android::hardware::hidl_vec<uint32_t> _n1) {
+ error = _s;
+ descriptor = _n1;
+ });
+ ASSERT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
- std::visit([buffer, nFrameWidth, nFrameHeight, format, usage, nStride](auto&& gralloc) {
- using Gralloc = std::remove_reference_t<decltype(gralloc)>;
- using Descriptor = typename Gralloc::Descriptor;
- using DescriptorInfo = typename Gralloc::DescriptorInfo;
- using Error = typename Gralloc::Error;
- using Format = typename Gralloc::Format;
- using Usage = typename Gralloc::Usage;
-
- Error error{};
- Descriptor descriptor{};
-
- DescriptorInfo descriptorInfo{};
- descriptorInfo.width = nFrameWidth;
- descriptorInfo.height = nFrameHeight;
- descriptorInfo.layerCount = 1;
- descriptorInfo.format = static_cast<Format>(format);
- descriptorInfo.usage = usage | Usage(BufferUsage::CPU_READ_OFTEN);
-
- gralloc.mMapper->createDescriptor(descriptorInfo,
- [&error, &descriptor](
- Error _s,
- const Descriptor& _n1) {
- error = _s;
- descriptor = _n1;
- });
- ASSERT_EQ(error, Error::NONE);
-
- gralloc.mAllocator->allocate(
- descriptor, 1,
- [&](Error _s, uint32_t _n1,
- const ::android::hardware::hidl_vec<
- ::android::hardware::hidl_handle>& _n2) {
- ASSERT_EQ(Error::NONE, _s);
- *nStride = _n1;
- buffer->omxBuffer.nativeHandle = _n2[0];
- buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
- buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
- buffer->omxBuffer.attr.anwBuffer.stride = _n1;
- buffer->omxBuffer.attr.anwBuffer.format =
- static_cast<PixelFormat>(descriptorInfo.format);
- buffer->omxBuffer.attr.anwBuffer.usage =
- static_cast<uint32_t>(descriptorInfo.usage);
- buffer->omxBuffer.attr.anwBuffer.layerCount =
- descriptorInfo.layerCount;
- buffer->omxBuffer.attr.anwBuffer.id =
- (static_cast<uint64_t>(getpid()) << 32) |
- bufferIdCounter.fetch_add(1, std::memory_order_relaxed);
- });
- }, grallocVar);
+ static volatile int32_t nextId = 0;
+ uint64_t id = static_cast<uint64_t>(getpid()) << 32;
+ allocator->allocate(
+ descriptor, 1,
+ [&](android::hardware::graphics::mapper::V2_0::Error _s, uint32_t _n1,
+ const ::android::hardware::hidl_vec<
+ ::android::hardware::hidl_handle>& _n2) {
+ ASSERT_EQ(android::hardware::graphics::mapper::V2_0::Error::NONE,
+ _s);
+ *nStride = _n1;
+ buffer->omxBuffer.nativeHandle = _n2[0];
+ buffer->omxBuffer.attr.anwBuffer.width = nFrameWidth;
+ buffer->omxBuffer.attr.anwBuffer.height = nFrameHeight;
+ buffer->omxBuffer.attr.anwBuffer.stride = _n1;
+ buffer->omxBuffer.attr.anwBuffer.format = descriptorInfo.format;
+ buffer->omxBuffer.attr.anwBuffer.usage = descriptorInfo.usage;
+ buffer->omxBuffer.attr.anwBuffer.layerCount =
+ descriptorInfo.layerCount;
+ buffer->omxBuffer.attr.anwBuffer.id =
+ id | static_cast<uint32_t>(android_atomic_inc(&nextId));
+ });
}
// allocate buffers needed on a component port
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index 08af26b..1575ba2 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -22,16 +22,6 @@
#endif
#include <getopt.h>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/allocator/3.0/IAllocator.h>
-#include <android/hardware/graphics/common/1.0/types.h>
-#include <android/hardware/graphics/common/1.1/types.h>
-#include <android/hardware/graphics/common/1.2/types.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <android/hardware/graphics/mapper/2.0/types.h>
-#include <android/hardware/graphics/mapper/3.0/IMapper.h>
-#include <android/hardware/graphics/mapper/3.0/types.h>
#include <media/stagefright/foundation/ALooper.h>
#include <utils/Condition.h>
#include <utils/List.h>
@@ -298,36 +288,6 @@
/*
* common functions declarations
*/
-struct GrallocV2 {
- using Format = android::hardware::graphics::common::V1_0::PixelFormat;
- using Usage = android::hardware::hidl_bitfield<
- android::hardware::graphics::common::V1_0::BufferUsage>;
-
- using IAllocator = android::hardware::graphics::allocator::V2_0::IAllocator;
-
- using IMapper = android::hardware::graphics::mapper::V2_0::IMapper;
- using Error = android::hardware::graphics::mapper::V2_0::Error;
- using Descriptor = android::hardware::graphics::mapper::V2_0::BufferDescriptor;
- using YCbCrLayout = android::hardware::graphics::mapper::V2_0::YCbCrLayout;
- using DescriptorInfo = IMapper::BufferDescriptorInfo;
- using Rect = IMapper::Rect;
-};
-
-struct GrallocV3 {
- using Format = android::hardware::graphics::common::V1_2::PixelFormat;
- using Usage = android::hardware::hidl_bitfield<
- android::hardware::graphics::common::V1_2::BufferUsage>;
-
- using IAllocator = android::hardware::graphics::allocator::V3_0::IAllocator;
-
- using IMapper = android::hardware::graphics::mapper::V3_0::IMapper;
- using Error = android::hardware::graphics::mapper::V3_0::Error;
- using Descriptor = android::hardware::graphics::mapper::V3_0::BufferDescriptor;
- using YCbCrLayout = android::hardware::graphics::mapper::V3_0::YCbCrLayout;
- using DescriptorInfo = IMapper::BufferDescriptorInfo;
- using Rect = IMapper::Rect;
-};
-
Return<android::hardware::media::omx::V1_0::Status> setRole(
sp<IOmxNode> omxNode, const char* role);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index 2280cee..a740a80 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -63,7 +63,6 @@
#include <media_video_hidl_test_common.h>
#include <system/window.h>
#include <fstream>
-#include <variant>
static ComponentTestEnvironment* gEnv = nullptr;
@@ -365,61 +364,6 @@
return Void();
};
-// Variant of mappers
-struct MapperV2 : public GrallocV2 {
- sp<IMapper> mMapper;
- MapperV2(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
- MapperV2() = default;
- android::hardware::Return<void> lock(
- void* buffer,
- Usage usage,
- const Rect& rect,
- const android::hardware::hidl_handle& handle,
- Error* error,
- void** data) {
- return mMapper->lock(buffer, usage, rect, handle,
- [error, data](Error e, void* d) {
- *error = e;
- *data = d;
- });
- }
-};
-struct MapperV3 : public GrallocV3 {
- sp<IMapper> mMapper;
- MapperV3(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
- MapperV3() = default;
- android::hardware::Return<void> lock(
- void* buffer,
- Usage usage,
- const Rect& rect,
- const android::hardware::hidl_handle& handle,
- Error* error,
- void** data) {
- return mMapper->lock(buffer, usage, rect, handle,
- [error, data](Error e, void* d, int32_t, int32_t) {
- *error = e;
- *data = d;
- });
- }
-};
-using MapperVar = std::variant<MapperV2, MapperV3>;
-// Initializes the MapperVar by trying services of different versions.
-bool initialize(MapperVar& mapperVar) {
- sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3 =
- android::hardware::graphics::mapper::V3_0::IMapper::getService();
- if (mapper3) {
- mapperVar.emplace<MapperV3>(std::move(mapper3));
- return true;
- }
- sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2 =
- android::hardware::graphics::mapper::V2_0::IMapper::getService();
- if (mapper2) {
- mapperVar.emplace<MapperV2>(std::move(mapper2));
- return true;
- }
- return false;
-}
-
// request VOP refresh
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
android::hardware::media::omx::V1_0::Status status;
@@ -630,166 +574,150 @@
int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
std::ifstream& eleStream) {
- MapperVar mapperVar;
- if (!initialize(mapperVar)) {
- EXPECT_TRUE(false) << "failed to obtain mapper service";
- return 1;
+ sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
+ android::hardware::graphics::mapper::V2_0::IMapper::getService();
+ EXPECT_NE(mapper.get(), nullptr);
+ if (mapper.get() == nullptr) return 1;
+
+ android::hardware::hidl_handle fence;
+ android::hardware::graphics::mapper::V2_0::IMapper::Rect rect;
+ android::hardware::graphics::mapper::V2_0::YCbCrLayout ycbcrLayout;
+ android::hardware::graphics::mapper::V2_0::Error error;
+ rect.left = 0;
+ rect.top = 0;
+ rect.width = buffer->omxBuffer.attr.anwBuffer.width;
+ rect.height = buffer->omxBuffer.attr.anwBuffer.height;
+
+ if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
+ format == PixelFormat::YCBCR_420_888) {
+ mapper->lockYCbCr(
+ buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
+ [&](android::hardware::graphics::mapper::V2_0::Error _e,
+ android::hardware::graphics::mapper::V2_0::YCbCrLayout _n1) {
+ error = _e;
+ ycbcrLayout = _n1;
+ });
+ EXPECT_EQ(error,
+ android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ return 1;
+
+ int size = ((rect.width * rect.height * 3) >> 1);
+ char* img = new char[size];
+ if (img == nullptr) return 1;
+ eleStream.read(img, size);
+ if (eleStream.gcount() != size) {
+ delete[] img;
+ return 1;
+ }
+
+ char* imgTmp = img;
+ char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
+ for (size_t y = rect.height; y > 0; --y) {
+ memcpy(ipBuffer, imgTmp, rect.width);
+ ipBuffer += ycbcrLayout.yStride;
+ imgTmp += rect.width;
+ }
+
+ if (format == PixelFormat::YV12)
+ EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
+ else if (format == PixelFormat::YCRCB_420_SP)
+ EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
+
+ ipBuffer = static_cast<char*>(ycbcrLayout.cb);
+ for (size_t y = rect.height >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.width >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cStride;
+ }
+ ipBuffer = static_cast<char*>(ycbcrLayout.cr);
+ for (size_t y = rect.height >> 1; y > 0; --y) {
+ for (int32_t x = 0; x < (rect.width >> 1); ++x) {
+ ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
+ }
+ ipBuffer += ycbcrLayout.cStride;
+ }
+
+ delete[] img;
+
+ mapper->unlock(buff,
+ [&](android::hardware::graphics::mapper::V2_0::Error _e,
+ android::hardware::hidl_handle _n1) {
+ error = _e;
+ fence = _n1;
+ });
+ EXPECT_EQ(error,
+ android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ return 1;
+ } else {
+ void* data;
+ mapper->lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
+ [&](android::hardware::graphics::mapper::V2_0::Error _e,
+ void* _n1) {
+ error = _e;
+ data = _n1;
+ });
+ EXPECT_EQ(error,
+ android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ return 1;
+
+ if (format == PixelFormat::BGRA_8888) {
+ char* ipBuffer = static_cast<char*>(data);
+ for (size_t y = rect.height; y > 0; --y) {
+ eleStream.read(ipBuffer, rect.width * 4);
+ if (eleStream.gcount() != rect.width * 4) return 1;
+ ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
+ }
+ } else {
+ EXPECT_TRUE(false) << "un expected pixel format";
+ return 1;
+ }
+
+ mapper->unlock(buff,
+ [&](android::hardware::graphics::mapper::V2_0::Error _e,
+ android::hardware::hidl_handle _n1) {
+ error = _e;
+ fence = _n1;
+ });
+ EXPECT_EQ(error,
+ android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ return 1;
}
- return std::visit([buffer, buff, format, &eleStream](auto&& mapper) -> int {
- using Gralloc = std::remove_reference_t<decltype(mapper)>;
- using Error = typename Gralloc::Error;
- using Rect = typename Gralloc::Rect;
- using Usage = typename Gralloc::Usage;
- using YCbCrLayout = typename Gralloc::YCbCrLayout;
-
- android::hardware::hidl_handle fence;
- Rect rect;
- YCbCrLayout ycbcrLayout;
- Error error;
- rect.left = 0;
- rect.top = 0;
- rect.width = buffer->omxBuffer.attr.anwBuffer.width;
- rect.height = buffer->omxBuffer.attr.anwBuffer.height;
-
- if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
- format == PixelFormat::YCBCR_420_888) {
- mapper.mMapper->lockYCbCr(
- buff,
- static_cast<Usage>(
- buffer->omxBuffer.attr.anwBuffer.usage),
- rect,
- fence,
- [&](Error _e,
- const YCbCrLayout& _n1) {
- error = _e;
- ycbcrLayout = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- int size = ((rect.width * rect.height * 3) >> 1);
- char* img = new char[size];
- if (img == nullptr) return 1;
- eleStream.read(img, size);
- if (eleStream.gcount() != size) {
- delete[] img;
- return 1;
- }
-
- char* imgTmp = img;
- char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
- for (size_t y = rect.height; y > 0; --y) {
- memcpy(ipBuffer, imgTmp, rect.width);
- ipBuffer += ycbcrLayout.yStride;
- imgTmp += rect.width;
- }
-
- if (format == PixelFormat::YV12)
- EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
- else if (format == PixelFormat::YCRCB_420_SP)
- EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
-
- ipBuffer = static_cast<char*>(ycbcrLayout.cb);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
- ipBuffer = static_cast<char*>(ycbcrLayout.cr);
- for (size_t y = rect.height >> 1; y > 0; --y) {
- for (int32_t x = 0; x < (rect.width >> 1); ++x) {
- ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
- }
- ipBuffer += ycbcrLayout.cStride;
- }
-
- delete[] img;
-
- mapper.mMapper->unlock(buff,
- [&](Error _e,
- const android::hardware::hidl_handle& _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
- } else {
- void* data;
- mapper.lock(
- buff,
- buffer->omxBuffer.attr.anwBuffer.usage,
- rect,
- fence,
- &error,
- &data);
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- if (format == PixelFormat::BGRA_8888) {
- char* ipBuffer = static_cast<char*>(data);
- for (size_t y = rect.height; y > 0; --y) {
- eleStream.read(ipBuffer, rect.width * 4);
- if (eleStream.gcount() != rect.width * 4) return 1;
- ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
- }
- } else {
- EXPECT_TRUE(false) << "un expected pixel format";
- return 1;
- }
-
- mapper.mMapper->unlock(
- buff,
- [&](Error _e, const android::hardware::hidl_handle& _n1) {
- error = _e;
- fence = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
- }
-
- return 0;
- }, mapperVar);
+ return 0;
}
int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
std::ifstream& eleStream) {
- MapperVar mapperVar;
- if (!initialize(mapperVar)) {
- EXPECT_TRUE(false) << "failed to obtain mapper service";
+ sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper =
+ android::hardware::graphics::mapper::V2_0::IMapper::getService();
+ EXPECT_NE(mapper.get(), nullptr);
+ if (mapper.get() == nullptr) return 1;
+
+ void* buff = nullptr;
+ android::hardware::graphics::mapper::V2_0::Error error;
+ mapper->importBuffer(
+ buffer->omxBuffer.nativeHandle,
+ [&](android::hardware::graphics::mapper::V2_0::Error _e, void* _n1) {
+ error = _e;
+ buff = _n1;
+ });
+ EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
return 1;
- }
- return std::visit([buffer, format, &eleStream](auto&& mapper) -> int {
- using Gralloc = std::remove_reference_t<decltype(mapper)>;
- using Error = typename Gralloc::Error;
+ if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
- void* buff = nullptr;
- Error error;
- mapper.mMapper->importBuffer(
- buffer->omxBuffer.nativeHandle,
- [&](Error _e, void* _n1) {
- error = _e;
- buff = _n1;
- });
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
+ error = mapper->freeBuffer(buff);
+ EXPECT_EQ(error, android::hardware::graphics::mapper::V2_0::Error::NONE);
+ if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
+ return 1;
- if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
-
- error = mapper.mMapper->freeBuffer(buff);
- EXPECT_EQ(error, Error::NONE);
- if (error != Error::NONE)
- return 1;
-
- return 0;
- }, mapperVar);
+ return 0;
}
int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
diff --git a/memtrack/1.0/default/Android.bp b/memtrack/1.0/default/Android.bp
index 76d7fc8..8aa33ee 100644
--- a/memtrack/1.0/default/Android.bp
+++ b/memtrack/1.0/default/Android.bp
@@ -23,7 +23,6 @@
"libbase",
"liblog",
"libhidlbase",
- "libhidltransport",
"libhardware",
"libutils",
"android.hardware.memtrack@1.0",
@@ -46,7 +45,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.memtrack@1.0",
],
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index a8406de..0af7f79 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -32,12 +32,11 @@
"android.hidl.memory@1.0",
"libgmock",
"libhidlmemory",
+ "libneuralnetworks_generated_test_harness",
"libneuralnetworks_utils",
],
header_libs: [
"libneuralnetworks_headers",
- "libneuralnetworks_generated_test_harness_headers",
- "libneuralnetworks_generated_tests",
],
}
@@ -45,6 +44,7 @@
name: "VtsHalNeuralNetworksV1_0TargetTestDefaults",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
+ "TestAssertions.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",
@@ -60,13 +60,12 @@
"android.hidl.memory@1.0",
"libgmock",
"libhidlmemory",
+ "libneuralnetworks_generated_test_harness",
"libneuralnetworks_utils",
"VtsHalNeuralNetworksV1_0_utils",
],
header_libs: [
"libneuralnetworks_headers",
- "libneuralnetworks_generated_test_harness_headers",
- "libneuralnetworks_generated_tests",
],
test_suites: ["general-tests"],
}
@@ -76,7 +75,9 @@
defaults: ["VtsHalNeuralNetworksV1_0TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_0_all_generated_V1_0_tests",
+ ],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
],
}
@@ -85,7 +86,9 @@
defaults: ["VtsHalNeuralNetworksV1_0TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_0_all_generated_V1_0_tests",
+ ],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
],
cflags: [
"-DPRESUBMIT_NOT_VTS",
diff --git a/neuralnetworks/1.0/vts/functional/BasicTests.cpp b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
index 945c406..5727ca4 100644
--- a/neuralnetworks/1.0/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
@@ -18,12 +18,7 @@
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
// create device test
TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
@@ -38,19 +33,14 @@
// initialization
TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
Return<void> ret =
- device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
- EXPECT_EQ(ErrorStatus::NONE, status);
- EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
- EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
- EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
- EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
- });
+ device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+ EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+ EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+ EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+ });
EXPECT_TRUE(ret.isOk());
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 40d2f4c..33a6fa5 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -15,10 +15,12 @@
*/
#include "GeneratedTestHarness.h"
+
#include "1.0/Callbacks.h"
#include "1.0/Utils.h"
#include "MemoryUtils.h"
#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
#include <android-base/logging.h>
#include <android/hardware/neuralnetworks/1.0/IDevice.h>
@@ -28,197 +30,169 @@
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
+#include <gtest/gtest.h>
#include <iostream>
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::IDevice;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Model;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::test_helper::compare;
-using ::test_helper::filter;
-using ::test_helper::for_all;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExample;
-using ::test_helper::resize_accordingly;
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using implementation::ExecutionCallback;
+using implementation::PreparedModelCallback;
+
+Model createModel(const TestModel& testModel) {
+ // Model operands.
+ hidl_vec<Operand> operands(testModel.operands.size());
+ size_t constCopySize = 0, constRefSize = 0;
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+
+ DataLocation loc = {};
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constCopySize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constCopySize += op.data.alignedSize();
+ } else if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constRefSize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constRefSize += op.data.alignedSize();
+ }
+
+ operands[i] = {.type = static_cast<OperandType>(op.type),
+ .dimensions = op.dimensions,
+ .numberOfConsumers = op.numberOfConsumers,
+ .scale = op.scale,
+ .zeroPoint = op.zeroPoint,
+ .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+ .location = loc};
+ }
+
+ // Model operations.
+ hidl_vec<Operation> operations(testModel.operations.size());
+ std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
+ [](const TestOperation& op) -> Operation {
+ return {.type = static_cast<OperationType>(op.type),
+ .inputs = op.inputs,
+ .outputs = op.outputs};
+ });
+
+ // Constant copies.
+ hidl_vec<uint8_t> operandValues(constCopySize);
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, operandValues.data() + operands[i].location.offset);
+ }
+ }
+
+ // Shared memory.
+ hidl_vec<hidl_memory> pools;
+ if (constRefSize > 0) {
+ hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+ CHECK_NE(pools[0].size(), 0u);
+
+ // load data
+ sp<IMemory> mappedMemory = mapMemory(pools[0]);
+ CHECK(mappedMemory.get() != nullptr);
+ uint8_t* mappedPtr =
+ reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
+ CHECK(mappedPtr != nullptr);
+
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, mappedPtr + operands[i].location.offset);
+ }
+ }
+ }
+
+ return {.operands = std::move(operands),
+ .operations = std::move(operations),
+ .inputIndexes = testModel.inputIndexes,
+ .outputIndexes = testModel.outputIndexes,
+ .operandValues = std::move(operandValues),
+ .pools = std::move(pools)};
+}
// Top level driver for models and examples generated by test_generator.py
// Test driver for those generated from ml/nn/runtime/test/spec
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples, float fpAtol,
- float fpRtol) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel) {
+ const Request request = createRequest(testModel);
- int example_no = 1;
- for (auto& example : examples) {
- SCOPED_TRACE(example_no++);
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& golden = example.operands.second;
+ // Launch execution.
+ sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+ Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(request, executionCallback);
+ ASSERT_TRUE(executionLaunchStatus.isOk());
+ EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
- CHECK(inputs.float16Operands.empty()) << "float16 is not supported in 1.0";
+ // Retrieve execution status.
+ executionCallback->wait();
+ ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
- }
- }
+ // Retrieve execution results.
+ const std::vector<TestBuffer> outputs = getOutputBuffers(request);
- MixedTyped test; // holding test results
-
- // Go through all outputs, initialize RequestArgument descriptors
- resize_accordingly(golden, test);
- for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- ASSERT_NE(0ull, pools[INPUT].size());
- ASSERT_NE(0ull, pools[OUTPUT].size());
-
- // load data
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
- ASSERT_NE(nullptr, inputMemory.get());
- ASSERT_NE(nullptr, outputMemory.get());
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
- ASSERT_NE(nullptr, inputPtr);
- ASSERT_NE(nullptr, outputPtr);
- inputMemory->update();
- outputMemory->update();
-
- // Go through all inputs, copy the values
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
-
- inputMemory->commit();
- outputMemory->commit();
-
- const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
-
- // launch execution
- sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
- Return<ErrorStatus> executionLaunchStatus =
- preparedModel->execute(request, executionCallback);
- ASSERT_TRUE(executionLaunchStatus.isOk());
- EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
-
- // retrieve execution status
- executionCallback->wait();
- ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
-
- // validate results
- outputMemory->read();
- copy_back(&test, outputs_info, outputPtr);
- outputMemory->commit();
- // Filter out don't cares
- MixedTyped filtered_golden = filter(golden, is_ignored);
- MixedTyped filtered_test = filter(test, is_ignored);
-
- // We want "close-enough" results for float
- compare(filtered_golden, filtered_test, fpAtol, fpRtol);
- }
+ // We want "close-enough" results.
+ checkResults(testModel, outputs);
}
-void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
- Model model = create_model();
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {
+ protected:
+ void Execute(const TestModel& testModel) {
+ Model model = createModel(testModel);
- // see if service can handle model
- bool fullySupportsModel = false;
- Return<void> supportedCall = device->getSupportedOperations(
- model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
- ASSERT_EQ(ErrorStatus::NONE, status);
- ASSERT_NE(0ul, supported.size());
- fullySupportsModel = std::all_of(supported.begin(), supported.end(),
- [](bool valid) { return valid; });
- });
- ASSERT_TRUE(supportedCall.isOk());
+ // see if service can handle model
+ bool fullySupportsModel = false;
+ Return<void> supportedCall = device->getSupportedOperations(
+ model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+ ASSERT_EQ(ErrorStatus::NONE, status);
+ ASSERT_NE(0ul, supported.size());
+ fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+ [](bool valid) { return valid; });
+ });
+ ASSERT_TRUE(supportedCall.isOk());
- // launch prepare model
- sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
- Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
- ASSERT_TRUE(prepareLaunchStatus.isOk());
- ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+ // launch prepare model
+ sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+ Return<ErrorStatus> prepareLaunchStatus =
+ device->prepareModel(model, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk());
+ ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
- // retrieve prepared model
- preparedModelCallback->wait();
- ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
- sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+ // retrieve prepared model
+ preparedModelCallback->wait();
+ ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+ sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
- // early termination if vendor service cannot fully prepare model
- if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
- ASSERT_EQ(nullptr, preparedModel.get());
- LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
- "prepare model that it does not support.";
- std::cout << "[ ] Early termination of test because vendor service cannot "
- "prepare model that it does not support."
- << std::endl;
- GTEST_SKIP();
+ // early termination if vendor service cannot fully prepare model
+ if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+ ASSERT_EQ(nullptr, preparedModel.get());
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "prepare model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "prepare model that it does not support."
+ << std::endl;
+ GTEST_SKIP();
+ }
+ EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+ ASSERT_NE(nullptr, preparedModel.get());
+
+ EvaluatePreparedModel(preparedModel, testModel);
}
- EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
- ASSERT_NE(nullptr, preparedModel.get());
+};
- float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
- EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
+TEST_P(GeneratedTest, Test) {
+ Execute(*mTestModel);
}
-} // namespace generated_tests
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+ [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
index 337eb0f..a42f271 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -19,22 +19,41 @@
#include <android/hardware/neuralnetworks/1.0/IDevice.h>
#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-using ::test_helper::MixedTypedExample;
+class GeneratedTestBase
+ : public NeuralnetworksHidlTest,
+ public ::testing::WithParamInterface<test_helper::TestModelManager::TestParam> {
+ protected:
+ void SetUp() override {
+ NeuralnetworksHidlTest::SetUp();
+ ASSERT_NE(mTestModel, nullptr);
+ }
-void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+ const test_helper::TestModel* mTestModel = GetParam().second;
+};
-} // namespace generated_tests
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ INSTANTIATE_TEST_SUITE_P( \
+ TestGenerated, TestSuite, \
+ ::testing::ValuesIn(::test_helper::TestModelManager::get().getTestModels(filter)), \
+ [](const auto& info) { return info.param.first; })
+
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {
+ protected:
+ void validateEverything(const Model& model, const Request& request);
+
+ private:
+ void validateModel(const Model& model);
+ void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request);
+};
+
+Model createModel(const ::test_helper::TestModel& testModel);
+
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.h b/neuralnetworks/1.0/vts/functional/GeneratedTests.h
deleted file mode 100644
index 5cabf68..0000000
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-#include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
-#include "TestHarness.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-
-std::vector<Request> createRequests(const std::vector<::test_helper::MixedTypedExample>& examples);
-
-} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
-
-namespace android::hardware::neuralnetworks::V1_0::generated_tests {
-
-using namespace android::hardware::neuralnetworks::V1_0::vts::functional;
-
-} // namespace android::hardware::neuralnetworks::V1_0::generated_tests
diff --git a/neuralnetworks/1.0/vts/functional/TestAssertions.cpp b/neuralnetworks/1.0/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..8fdc98d
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/TestAssertions.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_0 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+ static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperandType, FLOAT32);
+CHECK_TEST_ENUM(OperandType, INT32);
+CHECK_TEST_ENUM(OperandType, UINT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_INT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_ASYMM);
+
+CHECK_TEST_ENUM(OperandLifeTime, TEMPORARY_VARIABLE);
+CHECK_TEST_ENUM(OperandLifeTime, MODEL_INPUT);
+CHECK_TEST_ENUM(OperandLifeTime, MODEL_OUTPUT);
+CHECK_TEST_ENUM(OperandLifeTime, CONSTANT_COPY);
+CHECK_TEST_ENUM(OperandLifeTime, CONSTANT_REFERENCE);
+CHECK_TEST_ENUM(OperandLifeTime, NO_VALUE);
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+
+#undef CHECK_TEST_ENUM
+
+} // namespace android::hardware::neuralnetworks::V1_0
diff --git a/neuralnetworks/1.0/vts/functional/Utils.cpp b/neuralnetworks/1.0/vts/functional/Utils.cpp
index 521e524..5de99fd 100644
--- a/neuralnetworks/1.0/vts/functional/Utils.cpp
+++ b/neuralnetworks/1.0/vts/functional/Utils.cpp
@@ -14,47 +14,106 @@
* limitations under the License.
*/
-#include "GeneratedTestHarness.h"
+#include "1.0/Utils.h"
+
+#include "MemoryUtils.h"
#include "TestHarness.h"
+#include <android-base/logging.h>
#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
-#include <cstring>
-#include <map>
+#include <algorithm>
#include <vector>
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
+namespace android::hardware::neuralnetworks {
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::test_helper::for_each;
-using ::test_helper::MixedTyped;
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using V1_0::DataLocation;
+using V1_0::Request;
+using V1_0::RequestArgument;
-template <typename T>
-void copy_back_(std::map<int, std::vector<T>>* dst, const std::vector<RequestArgument>& ra,
- char* src) {
- for_each<T>(*dst, [&ra, src](int index, std::vector<T>& m) {
- ASSERT_EQ(m.size(), ra[index].location.length / sizeof(T));
- char* begin = src + ra[index].location.offset;
- memcpy(m.data(), begin, ra[index].location.length);
- });
+constexpr uint32_t kInputPoolIndex = 0;
+constexpr uint32_t kOutputPoolIndex = 1;
+
+Request createRequest(const TestModel& testModel) {
+ // Model inputs.
+ hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
+ size_t inputSize = 0;
+ for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+ const auto& op = testModel.operands[testModel.inputIndexes[i]];
+ if (op.data.size() == 0) {
+ // Omitted input.
+ inputs[i] = {.hasNoValue = true};
+ } else {
+ DataLocation loc = {.poolIndex = kInputPoolIndex,
+ .offset = static_cast<uint32_t>(inputSize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ inputSize += op.data.alignedSize();
+ inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+ }
+ }
+
+ // Model outputs.
+ hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
+ size_t outputSize = 0;
+ for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
+ const auto& op = testModel.operands[testModel.outputIndexes[i]];
+
+ // In the case of zero-sized output, we should at least provide a one-byte buffer.
+ // This is because zero-sized tensors are only supported internally to the driver, or
+ // reported in output shapes. It is illegal for the client to pre-specify a zero-sized
+ // tensor as model output. Otherwise, we will have two semantic conflicts:
+ // - "Zero dimension" conflicts with "unspecified dimension".
+ // - "Omitted operand buffer" conflicts with "zero-sized operand buffer".
+ size_t bufferSize = std::max<size_t>(op.data.size(), 1);
+
+ DataLocation loc = {.poolIndex = kOutputPoolIndex,
+ .offset = static_cast<uint32_t>(outputSize),
+ .length = static_cast<uint32_t>(bufferSize)};
+ outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
+ outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+ }
+
+ // Allocate memory pools.
+ hidl_vec<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+ nn::allocateSharedMemory(outputSize)};
+ CHECK_NE(pools[kInputPoolIndex].size(), 0u);
+ CHECK_NE(pools[kOutputPoolIndex].size(), 0u);
+ sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex]);
+ CHECK(inputMemory.get() != nullptr);
+ uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
+ CHECK(inputPtr != nullptr);
+
+ // Copy input data to the memory pool.
+ for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+ const auto& op = testModel.operands[testModel.inputIndexes[i]];
+ if (op.data.size() > 0) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, inputPtr + inputs[i].location.offset);
+ }
+ }
+
+ return {.inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
}
-void copy_back(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
- copy_back_(&dst->float32Operands, ra, src);
- copy_back_(&dst->int32Operands, ra, src);
- copy_back_(&dst->quant8AsymmOperands, ra, src);
- copy_back_(&dst->quant16SymmOperands, ra, src);
- copy_back_(&dst->float16Operands, ra, src);
- copy_back_(&dst->bool8Operands, ra, src);
- copy_back_(&dst->quant8ChannelOperands, ra, src);
- copy_back_(&dst->quant16AsymmOperands, ra, src);
- copy_back_(&dst->quant8SymmOperands, ra, src);
- static_assert(9 == MixedTyped::kNumTypes,
- "Number of types in MixedTyped changed, but copy_back function wasn't updated");
+std::vector<TestBuffer> getOutputBuffers(const Request& request) {
+ sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex]);
+ CHECK(outputMemory.get() != nullptr);
+ uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
+ CHECK(outputPtr != nullptr);
+
+ // Copy out output results.
+ std::vector<TestBuffer> outputBuffers;
+ for (const auto& output : request.outputs) {
+ outputBuffers.emplace_back(output.location.length, outputPtr + output.location.offset);
+ }
+
+ return outputBuffers;
}
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index 72c4a2b..9854395 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -16,19 +16,13 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "VtsHalNeuralnetworks.h"
-#include "1.0/Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using implementation::PreparedModelCallback;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -37,9 +31,9 @@
SCOPED_TRACE(message + " [getSupportedOperations]");
Return<void> ret =
- device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
- EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
- });
+ device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+ EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+ });
EXPECT_TRUE(ret.isOk());
}
@@ -48,7 +42,6 @@
SCOPED_TRACE(message + " [prepareModel]");
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
@@ -94,13 +87,13 @@
static uint32_t addOperand(Model* model) {
return hidl_vec_push_back(&model->operands,
{
- .type = OperandType::INT32,
- .dimensions = {},
- .numberOfConsumers = 0,
- .scale = 0.0f,
- .zeroPoint = 0,
- .lifetime = OperandLifeTime::MODEL_INPUT,
- .location = {.poolIndex = 0, .offset = 0, .length = 0},
+ .type = OperandType::INT32,
+ .dimensions = {},
+ .numberOfConsumers = 0,
+ .scale = 0.0f,
+ .zeroPoint = 0,
+ .lifetime = OperandLifeTime::MODEL_INPUT,
+ .location = {.poolIndex = 0, .offset = 0, .length = 0},
});
}
@@ -114,10 +107,10 @@
///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
static const int32_t invalidOperandTypes[] = {
- static_cast<int32_t>(OperandType::FLOAT32) - 1, // lower bound fundamental
- static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1, // upper bound fundamental
- static_cast<int32_t>(OperandType::OEM) - 1, // lower bound OEM
- static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1, // upper bound OEM
+ static_cast<int32_t>(OperandType::FLOAT32) - 1, // lower bound fundamental
+ static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1, // upper bound fundamental
+ static_cast<int32_t>(OperandType::OEM) - 1, // lower bound OEM
+ static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1, // upper bound OEM
};
static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
@@ -210,7 +203,7 @@
static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_0::Model& model) {
for (size_t operand = 0; operand < model.operands.size(); ++operand) {
const std::vector<int32_t> invalidZeroPoints =
- getInvalidZeroPoints(model.operands[operand].type);
+ getInvalidZeroPoints(model.operands[operand].type);
for (int32_t invalidZeroPoint : invalidZeroPoints) {
const std::string message = "mutateOperandZeroPointTest: operand " +
std::to_string(operand) + " has zero point of " +
@@ -242,18 +235,18 @@
break;
case OperandType::TENSOR_FLOAT32:
newOperand.dimensions =
- operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+ operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
newOperand.scale = 0.0f;
newOperand.zeroPoint = 0;
break;
case OperandType::TENSOR_INT32:
newOperand.dimensions =
- operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+ operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
newOperand.zeroPoint = 0;
break;
case OperandType::TENSOR_QUANT8_ASYMM:
newOperand.dimensions =
- operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+ operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
break;
case OperandType::OEM:
@@ -303,10 +296,10 @@
///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
static const int32_t invalidOperationTypes[] = {
- static_cast<int32_t>(OperationType::ADD) - 1, // lower bound fundamental
- static_cast<int32_t>(OperationType::TANH) + 1, // upper bound fundamental
- static_cast<int32_t>(OperationType::OEM_OPERATION) - 1, // lower bound OEM
- static_cast<int32_t>(OperationType::OEM_OPERATION) + 1, // upper bound OEM
+ static_cast<int32_t>(OperationType::ADD) - 1, // lower bound fundamental
+ static_cast<int32_t>(OperationType::TANH) + 1, // upper bound fundamental
+ static_cast<int32_t>(OperationType::OEM_OPERATION) - 1, // lower bound OEM
+ static_cast<int32_t>(OperationType::OEM_OPERATION) + 1, // upper bound OEM
};
static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
@@ -317,7 +310,7 @@
std::to_string(invalidOperationType);
validate(device, message, model, [operation, invalidOperationType](Model* model) {
model->operations[operation].type =
- static_cast<OperationType>(invalidOperationType);
+ static_cast<OperationType>(invalidOperationType);
});
}
}
@@ -470,7 +463,7 @@
static void addOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
for (size_t operation = 0; operation < model.operations.size(); ++operation) {
const std::string message =
- "addOperationOutputTest: operation " + std::to_string(operation);
+ "addOperationOutputTest: operation " + std::to_string(operation);
validate(device, message, model, [operation](Model* model) {
uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -498,9 +491,4 @@
addOperationOutputTest(device, model);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index 058eb25..d8f3e65 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -16,27 +16,13 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
#include "1.0/Callbacks.h"
-#include "MemoryUtils.h"
-#include "TestHarness.h"
+#include "GeneratedTestHarness.h"
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using implementation::ExecutionCallback;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -50,7 +36,6 @@
SCOPED_TRACE(message + " [execute]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
ASSERT_TRUE(executeLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
@@ -102,108 +87,10 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
-
- std::vector<Request> requests;
-
- for (const MixedTypedExample& example : examples) {
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& outputs = example.operands.second;
-
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
-
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
- }
- }
-
- // Go through all outputs, initialize RequestArgument descriptors
- for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
- return {};
- }
-
- // map pool
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- if (inputMemory == nullptr) {
- return {};
- }
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- if (inputPtr == nullptr) {
- return {};
- }
-
- // initialize pool
- inputMemory->update();
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
- inputMemory->commit();
-
- requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
- }
-
- return requests;
+void ValidationTest::validateRequest(const sp<IPreparedModel>& preparedModel,
+ const Request& request) {
+ removeInputTest(preparedModel, request);
+ removeOutputTest(preparedModel, request);
}
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
- // validate each request
- for (const Request& request : requests) {
- removeInputTest(preparedModel, request);
- removeOutputTest(preparedModel, request);
- }
-}
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index 95b7ad3..9ee4e37 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,21 +17,18 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
#include "VtsHalNeuralnetworks.h"
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
#include <android-base/logging.h>
-#include "1.0/Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+using implementation::PreparedModelCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void createPreparedModel(const sp<IDevice>& device, const V1_0::Model& model,
+static void createPreparedModel(const sp<IDevice>& device, const Model& model,
sp<IPreparedModel>* preparedModel) {
ASSERT_NE(nullptr, preparedModel);
@@ -48,7 +45,6 @@
// launch prepare model
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
@@ -79,10 +75,6 @@
}
// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
// This has to return a "new" object because it is freed inside
// ::testing::AddGlobalTestEnvironment when the gtest is being torn down
@@ -95,14 +87,8 @@
}
// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
void NeuralnetworksHidlTest::SetUp() {
::testing::VtsHalHidlTargetTestBase::SetUp();
- device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
- NeuralnetworksHidlEnvironment::getInstance());
#ifdef PRESUBMIT_NOT_VTS
const std::string name =
@@ -117,29 +103,30 @@
}
void NeuralnetworksHidlTest::TearDown() {
- device = nullptr;
::testing::VtsHalHidlTargetTestBase::TearDown();
}
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
+void ValidationTest::validateEverything(const Model& model, const Request& request) {
validateModel(model);
// create IPreparedModel
sp<IPreparedModel> preparedModel;
- ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
- if (preparedModel == nullptr) {
- return;
- }
+ createPreparedModel(device, model, &preparedModel);
+ if (preparedModel == nullptr) return;
- validateRequests(preparedModel, requests);
+ validateRequest(preparedModel, request);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+TEST_P(ValidationTest, Test) {
+ const Model model = createModel(*mTestModel);
+ const Request request = createRequest(*mTestModel);
+ ASSERT_FALSE(mTestModel->expectFailure);
+ validateEverything(model, request);
+}
+
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index c32a91d..fa9ad3b 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -28,20 +28,16 @@
#include <iostream>
#include <vector>
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
// A class for test environment setup
class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
- NeuralnetworksHidlEnvironment();
- ~NeuralnetworksHidlEnvironment() override;
+ NeuralnetworksHidlEnvironment() = default;
- public:
+ public:
static NeuralnetworksHidlEnvironment* getInstance();
void registerTestServices() override;
};
@@ -50,36 +46,17 @@
class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
- public:
- NeuralnetworksHidlTest();
- ~NeuralnetworksHidlTest() override;
+ public:
+ NeuralnetworksHidlTest() = default;
void SetUp() override;
void TearDown() override;
- protected:
- sp<IDevice> device;
+ protected:
+ const sp<IDevice> device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
+ NeuralnetworksHidlEnvironment::getInstance());
};
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
- protected:
- void validateEverything(const Model& model, const std::vector<Request>& request);
-
- private:
- void validateModel(const Model& model);
- void validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests);
-};
-
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_0
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_0::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
index b270c20..274cb58 100644
--- a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
@@ -17,40 +17,39 @@
#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
+#include <android-base/logging.h>
#include <android/hardware/neuralnetworks/1.0/types.h>
#include <algorithm>
#include <vector>
#include "TestHarness.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
+namespace android::hardware::neuralnetworks {
-void copy_back(::test_helper::MixedTyped* dst, const std::vector<V1_0::RequestArgument>& ra,
- char* src);
+// Create HIDL Request from the TestModel struct.
+V1_0::Request createRequest(const ::test_helper::TestModel& testModel);
+
+// After execution, copy out output results from the output memory pool.
+std::vector<::test_helper::TestBuffer> getOutputBuffers(const V1_0::Request& request);
// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
// so this is efficiently accomplished by moving the element to the end and
// resizing the hidl_vec to one less.
template <typename Type>
inline void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
- if (vec) {
- std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
- vec->resize(vec->size() - 1);
- }
+ CHECK(vec != nullptr);
+ std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+ vec->resize(vec->size() - 1);
}
template <typename Type>
inline uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
- // assume vec is valid
+ CHECK(vec != nullptr);
const uint32_t index = vec->size();
vec->resize(index + 1);
(*vec)[index] = value;
return index;
}
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks
#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 1b31008..c197e6d 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -18,6 +18,7 @@
name: "VtsHalNeuralNetworksV1_1TargetTestDefaults",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
+ "TestAssertions.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",
@@ -34,33 +35,25 @@
"android.hidl.memory@1.0",
"libgmock",
"libhidlmemory",
+ "libneuralnetworks_generated_test_harness",
"libneuralnetworks_utils",
"VtsHalNeuralNetworksV1_0_utils",
],
header_libs: [
"libneuralnetworks_headers",
- "libneuralnetworks_generated_test_harness_headers",
- "libneuralnetworks_generated_tests",
],
test_suites: ["general-tests"],
}
-// Tests for V1_0 models using the V1_1 HAL.
-cc_test {
- name: "VtsHalNeuralnetworksV1_1CompatV1_0TargetTest",
- defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
- srcs: [
- ":VtsHalNeuralNetworksV1_1_all_generated_V1_0_tests",
- ],
-}
-
-// Tests for V1_1 models.
cc_test {
name: "VtsHalNeuralnetworksV1_1TargetTest",
defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_1_all_generated_V1_1_tests",
+ ],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
+ "neuralnetworks_generated_V1_1_example",
],
}
@@ -69,7 +62,10 @@
defaults: ["VtsHalNeuralNetworksV1_1TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_1_all_generated_V1_1_tests",
+ ],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
+ "neuralnetworks_generated_V1_1_example",
],
cflags: [
"-DPRESUBMIT_NOT_VTS",
diff --git a/neuralnetworks/1.1/vts/functional/BasicTests.cpp b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
index ed59a2d..c239c51 100644
--- a/neuralnetworks/1.1/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
@@ -18,12 +18,10 @@
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
+
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
// create device test
TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
@@ -38,21 +36,16 @@
// initialization
TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
Return<void> ret =
- device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
- EXPECT_EQ(ErrorStatus::NONE, status);
- EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
- EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
- EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
- EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
- EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
- EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
- });
+ device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
+ EXPECT_EQ(ErrorStatus::NONE, status);
+ EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+ EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+ EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+ EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+ EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
+ EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
+ });
EXPECT_TRUE(ret.isOk());
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
index e7d59ec..6ed5bc1 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
@@ -24,211 +24,183 @@
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
+#include <gtest/gtest.h>
#include <iostream>
#include "1.0/Callbacks.h"
#include "1.0/Utils.h"
#include "MemoryUtils.h"
#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-using ::android::hardware::neuralnetworks::V1_1::ExecutionPreference;
-using ::android::hardware::neuralnetworks::V1_1::IDevice;
-using ::android::hardware::neuralnetworks::V1_1::Model;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::test_helper::compare;
-using ::test_helper::filter;
-using ::test_helper::for_all;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExample;
-using ::test_helper::resize_accordingly;
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using V1_0::DataLocation;
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+using V1_0::Request;
+using V1_0::implementation::ExecutionCallback;
+using V1_0::implementation::PreparedModelCallback;
+
+Model createModel(const TestModel& testModel) {
+ // Model operands.
+ hidl_vec<Operand> operands(testModel.operands.size());
+ size_t constCopySize = 0, constRefSize = 0;
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+
+ DataLocation loc = {};
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constCopySize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constCopySize += op.data.alignedSize();
+ } else if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constRefSize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constRefSize += op.data.alignedSize();
+ }
+
+ operands[i] = {.type = static_cast<OperandType>(op.type),
+ .dimensions = op.dimensions,
+ .numberOfConsumers = op.numberOfConsumers,
+ .scale = op.scale,
+ .zeroPoint = op.zeroPoint,
+ .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+ .location = loc};
+ }
+
+ // Model operations.
+ hidl_vec<Operation> operations(testModel.operations.size());
+ std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
+ [](const TestOperation& op) -> Operation {
+ return {.type = static_cast<OperationType>(op.type),
+ .inputs = op.inputs,
+ .outputs = op.outputs};
+ });
+
+ // Constant copies.
+ hidl_vec<uint8_t> operandValues(constCopySize);
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, operandValues.data() + operands[i].location.offset);
+ }
+ }
+
+ // Shared memory.
+ hidl_vec<hidl_memory> pools;
+ if (constRefSize > 0) {
+ hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+ CHECK_NE(pools[0].size(), 0u);
+
+ // load data
+ sp<IMemory> mappedMemory = mapMemory(pools[0]);
+ CHECK(mappedMemory.get() != nullptr);
+ uint8_t* mappedPtr =
+ reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
+ CHECK(mappedPtr != nullptr);
+
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, mappedPtr + operands[i].location.offset);
+ }
+ }
+ }
+
+ return {.operands = std::move(operands),
+ .operations = std::move(operations),
+ .inputIndexes = testModel.inputIndexes,
+ .outputIndexes = testModel.outputIndexes,
+ .operandValues = std::move(operandValues),
+ .pools = std::move(pools),
+ .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
+}
// Top level driver for models and examples generated by test_generator.py
// Test driver for those generated from ml/nn/runtime/test/spec
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, float fpAtol, float fpRtol) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel) {
+ const Request request = createRequest(testModel);
- int example_no = 1;
- for (auto& example : examples) {
- SCOPED_TRACE(example_no++);
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& golden = example.operands.second;
+ // Launch execution.
+ sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+ Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(request, executionCallback);
+ ASSERT_TRUE(executionLaunchStatus.isOk());
+ EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
- const bool hasFloat16Inputs = !inputs.float16Operands.empty();
- if (hasRelaxedFloat32Model || hasFloat16Inputs) {
- // TODO: Adjust the error limit based on testing.
- // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
- fpAtol = 5.0f * 0.0009765625f;
- // Set the relative tolerance to be 5ULP of the corresponding FP precision.
- fpRtol = 5.0f * 0.0009765625f;
- }
+ // Retrieve execution status.
+ executionCallback->wait();
+ ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
- }
- }
+ // Retrieve execution results.
+ const std::vector<TestBuffer> outputs = getOutputBuffers(request);
- MixedTyped test; // holding test results
-
- // Go through all outputs, initialize RequestArgument descriptors
- resize_accordingly(golden, test);
- for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- ASSERT_NE(0ull, pools[INPUT].size());
- ASSERT_NE(0ull, pools[OUTPUT].size());
-
- // load data
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
- ASSERT_NE(nullptr, inputMemory.get());
- ASSERT_NE(nullptr, outputMemory.get());
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
- ASSERT_NE(nullptr, inputPtr);
- ASSERT_NE(nullptr, outputPtr);
- inputMemory->update();
- outputMemory->update();
-
- // Go through all inputs, copy the values
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
-
- inputMemory->commit();
- outputMemory->commit();
-
- const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
-
- // launch execution
- sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
- Return<ErrorStatus> executionLaunchStatus =
- preparedModel->execute(request, executionCallback);
- ASSERT_TRUE(executionLaunchStatus.isOk());
- EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
-
- // retrieve execution status
- executionCallback->wait();
- ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
-
- // validate results
- outputMemory->read();
- copy_back(&test, outputs_info, outputPtr);
- outputMemory->commit();
- // Filter out don't cares
- MixedTyped filtered_golden = filter(golden, is_ignored);
- MixedTyped filtered_test = filter(test, is_ignored);
-
- // We want "close-enough" results for float
- compare(filtered_golden, filtered_test, fpAtol, fpRtol);
- }
+ // We want "close-enough" results.
+ checkResults(testModel, outputs);
}
-void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
- Model model = create_model();
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {
+ protected:
+ void Execute(const TestModel& testModel) {
+ Model model = createModel(testModel);
- // see if service can handle model
- bool fullySupportsModel = false;
- Return<void> supportedCall = device->getSupportedOperations_1_1(
- model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
- ASSERT_EQ(ErrorStatus::NONE, status);
- ASSERT_NE(0ul, supported.size());
- fullySupportsModel = std::all_of(supported.begin(), supported.end(),
- [](bool valid) { return valid; });
- });
- ASSERT_TRUE(supportedCall.isOk());
+ // see if service can handle model
+ bool fullySupportsModel = false;
+ Return<void> supportedCall = device->getSupportedOperations_1_1(
+ model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
+ ASSERT_EQ(ErrorStatus::NONE, status);
+ ASSERT_NE(0ul, supported.size());
+ fullySupportsModel = std::all_of(supported.begin(), supported.end(),
+ [](bool valid) { return valid; });
+ });
+ ASSERT_TRUE(supportedCall.isOk());
- // launch prepare model
- sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
- Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
- model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
- ASSERT_TRUE(prepareLaunchStatus.isOk());
- ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+ // launch prepare model
+ sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+ Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
+ model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
+ ASSERT_TRUE(prepareLaunchStatus.isOk());
+ ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
- // retrieve prepared model
- preparedModelCallback->wait();
- ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
- sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+ // retrieve prepared model
+ preparedModelCallback->wait();
+ ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+ sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
- // early termination if vendor service cannot fully prepare model
- if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
- ASSERT_EQ(nullptr, preparedModel.get());
- LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
- "prepare model that it does not support.";
- std::cout << "[ ] Early termination of test because vendor service cannot "
- "prepare model that it does not support."
- << std::endl;
- GTEST_SKIP();
+ // early termination if vendor service cannot fully prepare model
+ if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
+ ASSERT_EQ(nullptr, preparedModel.get());
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "prepare model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "prepare model that it does not support."
+ << std::endl;
+ GTEST_SKIP();
+ }
+ EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+ ASSERT_NE(nullptr, preparedModel.get());
+
+ EvaluatePreparedModel(preparedModel, testModel);
}
- EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
- ASSERT_NE(nullptr, preparedModel.get());
+};
- EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f);
+TEST_P(GeneratedTest, Test) {
+ Execute(*mTestModel);
}
-} // namespace generated_tests
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+ [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
index 64b88dd..7cb9bdc 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
@@ -18,25 +18,43 @@
#define ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
-#include <functional>
-#include <vector>
#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
- std::function<bool(int)> is_ignored,
- const std::vector<::test_helper::MixedTypedExample>& examples);
+class GeneratedTestBase
+ : public NeuralnetworksHidlTest,
+ public ::testing::WithParamInterface<test_helper::TestModelManager::TestParam> {
+ protected:
+ void SetUp() override {
+ NeuralnetworksHidlTest::SetUp();
+ ASSERT_NE(mTestModel, nullptr);
+ }
-} // namespace generated_tests
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+ const test_helper::TestModel* mTestModel = GetParam().second;
+};
+
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ INSTANTIATE_TEST_SUITE_P( \
+ TestGenerated, TestSuite, \
+ ::testing::ValuesIn(::test_helper::TestModelManager::get().getTestModels(filter)), \
+ [](const auto& info) { return info.param.first; })
+
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {
+ protected:
+ void validateEverything(const Model& model, const V1_0::Request& request);
+
+ private:
+ void validateModel(const Model& model);
+ void validateRequest(const sp<V1_0::IPreparedModel>& preparedModel,
+ const V1_0::Request& request);
+};
+
+Model createModel(const ::test_helper::TestModel& testModel);
+
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.h b/neuralnetworks/1.1/vts/functional/GeneratedTests.h
deleted file mode 100644
index 80442bf..0000000
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-#include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
-#include "TestHarness.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-
-std::vector<Request> createRequests(const std::vector<::test_helper::MixedTypedExample>& examples);
-
-} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
-
-namespace android::hardware::neuralnetworks::V1_1::generated_tests {
-
-using namespace android::hardware::neuralnetworks::V1_1::vts::functional;
-
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-
-} // namespace android::hardware::neuralnetworks::V1_1::generated_tests
diff --git a/neuralnetworks/1.1/vts/functional/TestAssertions.cpp b/neuralnetworks/1.1/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..f4a49bc
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/TestAssertions.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_1 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+ static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+CHECK_TEST_ENUM(OperationType, BATCH_TO_SPACE_ND);
+CHECK_TEST_ENUM(OperationType, DIV);
+CHECK_TEST_ENUM(OperationType, MEAN);
+CHECK_TEST_ENUM(OperationType, PAD);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_BATCH_ND);
+CHECK_TEST_ENUM(OperationType, SQUEEZE);
+CHECK_TEST_ENUM(OperationType, STRIDED_SLICE);
+CHECK_TEST_ENUM(OperationType, SUB);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE);
+
+#undef CHECK_TEST_ENUM
+
+} // namespace android::hardware::neuralnetworks::V1_1
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index fb80d13..e617219 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -18,20 +18,17 @@
#include "1.0/Callbacks.h"
#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_0::Operand;
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::OperandType;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+using V1_0::implementation::PreparedModelCallback;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -51,7 +48,6 @@
SCOPED_TRACE(message + " [prepareModel_1_1]");
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus =
device->prepareModel_1_1(model, preference, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
@@ -483,8 +479,9 @@
for (int32_t preference : invalidExecutionPreferences) {
const std::string message =
"mutateExecutionPreferenceTest: preference " + std::to_string(preference);
- validate(device, message, model, [](Model*) {},
- static_cast<ExecutionPreference>(preference));
+ validate(
+ device, message, model, [](Model*) {},
+ static_cast<ExecutionPreference>(preference));
}
}
@@ -508,9 +505,4 @@
mutateExecutionPreferenceTest(device, model);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index c549728..a4e4ade 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -16,32 +16,17 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
#include "1.0/Callbacks.h"
#include "1.0/Utils.h"
-#include "MemoryUtils.h"
-#include "TestHarness.h"
+#include "GeneratedTestHarness.h"
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_1::IPreparedModel;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::test_helper::for_all;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExample;
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Request;
+using V1_0::implementation::ExecutionCallback;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -55,7 +40,6 @@
SCOPED_TRACE(message + " [execute]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
ASSERT_TRUE(executeLaunchStatus.isOk());
ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
@@ -87,108 +71,10 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
-
- std::vector<Request> requests;
-
- for (auto& example : examples) {
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& outputs = example.operands.second;
-
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
-
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
- }
- }
-
- // Go through all outputs, initialize RequestArgument descriptors
- for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
- return {};
- }
-
- // map pool
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- if (inputMemory == nullptr) {
- return {};
- }
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- if (inputPtr == nullptr) {
- return {};
- }
-
- // initialize pool
- inputMemory->update();
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
- inputMemory->commit();
-
- requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
- }
-
- return requests;
+void ValidationTest::validateRequest(const sp<IPreparedModel>& preparedModel,
+ const Request& request) {
+ removeInputTest(preparedModel, request);
+ removeOutputTest(preparedModel, request);
}
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
- // validate each request
- for (const Request& request : requests) {
- removeInputTest(preparedModel, request);
- removeOutputTest(preparedModel, request);
- }
-}
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index 12bdd3f..2c1a839 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,21 +17,21 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
#include "VtsHalNeuralnetworks.h"
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
#include <android-base/logging.h>
-#include "1.0/Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Request;
+using V1_0::implementation::PreparedModelCallback;
-using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
-
-static void createPreparedModel(const sp<IDevice>& device, const V1_1::Model& model,
+static void createPreparedModel(const sp<IDevice>& device, const Model& model,
sp<IPreparedModel>* preparedModel) {
ASSERT_NE(nullptr, preparedModel);
@@ -48,7 +48,6 @@
// launch prepare model
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
ASSERT_TRUE(prepareLaunchStatus.isOk());
@@ -80,10 +79,6 @@
}
// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
// This has to return a "new" object because it is freed inside
// ::testing::AddGlobalTestEnvironment when the gtest is being torn down
@@ -96,14 +91,8 @@
}
// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
void NeuralnetworksHidlTest::SetUp() {
::testing::VtsHalHidlTargetTestBase::SetUp();
- device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
- NeuralnetworksHidlEnvironment::getInstance());
#ifdef PRESUBMIT_NOT_VTS
const std::string name =
@@ -118,11 +107,10 @@
}
void NeuralnetworksHidlTest::TearDown() {
- device = nullptr;
::testing::VtsHalHidlTargetTestBase::TearDown();
}
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
+void ValidationTest::validateEverything(const Model& model, const Request& request) {
validateModel(model);
// create IPreparedModel
@@ -132,15 +120,19 @@
return;
}
- validateRequests(preparedModel, requests);
+ validateRequest(preparedModel, request);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+TEST_P(ValidationTest, Test) {
+ const Model model = createModel(*mTestModel);
+ const Request request = createRequest(*mTestModel);
+ ASSERT_FALSE(mTestModel->expectFailure);
+ validateEverything(model, request);
+}
+
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index 3156784..3d6f2ea 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -29,28 +29,16 @@
#include <iostream>
#include <vector>
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
+#include "TestHarness.h"
-using V1_0::DeviceStatus;
-using V1_0::ErrorStatus;
-using V1_0::IPreparedModel;
-using V1_0::Operand;
-using V1_0::OperandType;
-using V1_0::Request;
-
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
// A class for test environment setup
class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
- NeuralnetworksHidlEnvironment();
- ~NeuralnetworksHidlEnvironment() override;
+ NeuralnetworksHidlEnvironment() = default;
- public:
+ public:
static NeuralnetworksHidlEnvironment* getInstance();
void registerTestServices() override;
};
@@ -59,36 +47,17 @@
class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
- public:
- NeuralnetworksHidlTest();
- ~NeuralnetworksHidlTest() override;
+ public:
+ NeuralnetworksHidlTest() = default;
void SetUp() override;
void TearDown() override;
- protected:
- sp<IDevice> device;
+ protected:
+ const sp<IDevice> device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
+ NeuralnetworksHidlEnvironment::getInstance());
};
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
- protected:
- void validateEverything(const Model& model, const std::vector<Request>& request);
-
- private:
- void validateModel(const Model& model);
- void validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests);
-};
-
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
-
-} // namespace functional
-} // namespace vts
-} // namespace V1_1
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_1::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index d83f9e6..ff20c12 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -64,14 +64,14 @@
* results, the developer could choose an ACCELERATOR type device for ML
* workloads, and reserve GPU for graphical rendering.
*
- * @param status Error status returned from querying the device type. Must be:
- * - NONE if the query was successful
- * - DEVICE_UNAVAILABLE if driver is offline or busy
- * - GENERAL_FAILURE if the query resulted in an
- * unspecified error
- * @param type The DeviceType of the device. Please note, this is not a
- * bitfield of DeviceTypes. Each device must only be of a
- * single DeviceType.
+ * @return status Error status returned from querying the device type. Must be:
+ * - NONE if the query was successful
+ * - DEVICE_UNAVAILABLE if driver is offline or busy
+ * - GENERAL_FAILURE if the query resulted in an
+ * unspecified error
+ * @return type The DeviceType of the device. Please note, this is not a
+ * bitfield of DeviceTypes. Each device must only be of a
+ * single DeviceType.
*/
getType() generates (ErrorStatus status, DeviceType type);
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 301ca5d..40ca809 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -18,6 +18,7 @@
name: "VtsHalNeuralNetworksV1_2TargetTestDefaults",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
+ "TestAssertions.cpp",
"ValidateModel.cpp",
"ValidateRequest.cpp",
"VtsHalNeuralnetworks.cpp",
@@ -37,48 +38,29 @@
"android.hidl.memory@1.0",
"libgmock",
"libhidlmemory",
+ "libneuralnetworks_generated_test_harness",
"libneuralnetworks_utils",
"VtsHalNeuralNetworksV1_0_utils",
],
header_libs: [
"libneuralnetworks_headers",
- "libneuralnetworks_generated_test_harness_headers",
- "libneuralnetworks_generated_tests",
],
test_suites: ["general-tests"],
}
-// Tests for V1_0 models using the V1_2 HAL.
-cc_test {
- name: "VtsHalNeuralnetworksV1_2CompatV1_0TargetTest",
- defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
- srcs: [
- ":VtsHalNeuralNetworksV1_2_all_generated_V1_0_tests",
- "ValidateBurst.cpp",
- ],
-}
-
-// Tests for V1_1 models using the V1_2 HAL.
-cc_test {
- name: "VtsHalNeuralnetworksV1_2CompatV1_1TargetTest",
- defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
- srcs: [
- ":VtsHalNeuralNetworksV1_2_all_generated_V1_1_tests",
- "ValidateBurst.cpp",
- ],
-}
-
-// Tests for V1_2 models.
cc_test {
name: "VtsHalNeuralnetworksV1_2TargetTest",
defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_2_all_generated_V1_2_tests",
"CompilationCachingTests.cpp",
- ":VtsHalNeuralNetworksV1_2_mobilenets", // CompilationCachingTests depend on MobileNets.
"ValidateBurst.cpp",
],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
+ "neuralnetworks_generated_V1_1_example",
+ "neuralnetworks_generated_V1_2_example",
+ ],
}
cc_test {
@@ -86,9 +68,14 @@
defaults: ["VtsHalNeuralNetworksV1_2TargetTestDefaults"],
srcs: [
"BasicTests.cpp",
- ":VtsHalNeuralNetworksV1_2_all_generated_V1_2_tests",
+ "CompilationCachingTests.cpp",
"ValidateBurst.cpp",
],
+ whole_static_libs: [
+ "neuralnetworks_generated_V1_0_example",
+ "neuralnetworks_generated_V1_1_example",
+ "neuralnetworks_generated_V1_2_example",
+ ],
cflags: [
"-DPRESUBMIT_NOT_VTS",
],
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 5c269df..86849d5 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -18,13 +18,10 @@
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
using V1_0::PerformanceInfo;
// create device test
@@ -113,9 +110,4 @@
});
EXPECT_TRUE(ret.isOk());
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/Callbacks.cpp b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
index a607a08..3972ad6 100644
--- a/neuralnetworks/1.2/vts/functional/Callbacks.cpp
+++ b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
@@ -24,6 +24,8 @@
namespace android::hardware::neuralnetworks::V1_2::implementation {
+using V1_0::ErrorStatus;
+
constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits<uint64_t>::max(),
.timeInDriver = std::numeric_limits<uint64_t>::max()};
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 5907646..90872d4 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -17,7 +17,6 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
#include <ftw.h>
#include <gtest/gtest.h>
#include <hidlmemory/mapping.h>
@@ -35,74 +34,32 @@
#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
-namespace android::hardware::neuralnetworks::V1_2 {
+// Forward declaration of the mobilenet generated test models in
+// frameworks/ml/nn/runtime/test/generated/.
namespace generated_tests::mobilenet_224_gender_basic_fixed {
-Model createTestModel();
+const ::test_helper::TestModel& get_test_model();
} // namespace generated_tests::mobilenet_224_gender_basic_fixed
-} // namespace android::hardware::neuralnetworks::V1_2
-
-namespace generated_tests::mobilenet_224_gender_basic_fixed {
-std::vector<test_helper::MixedTypedExample>& get_examples();
-} // namespace generated_tests::mobilenet_224_gender_basic_fixed
-
-namespace android::hardware::neuralnetworks::V1_2::generated_tests::mobilenet_quantized {
-Model createTestModel();
-} // namespace android::hardware::neuralnetworks::V1_2::generated_tests::mobilenet_quantized
namespace generated_tests::mobilenet_quantized {
-std::vector<test_helper::MixedTypedExample>& get_examples();
+const ::test_helper::TestModel& get_test_model();
} // namespace generated_tests::mobilenet_quantized
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_1::ExecutionPreference;
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
+using namespace test_helper;
+using implementation::PreparedModelCallback;
+using V1_0::ErrorStatus;
+using V1_1::ExecutionPreference;
namespace float32_model {
-constexpr auto createTestModel = ::android::hardware::neuralnetworks::V1_2::generated_tests::
- mobilenet_224_gender_basic_fixed::createTestModel;
-constexpr auto get_examples = ::generated_tests::mobilenet_224_gender_basic_fixed::get_examples;
-
-// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
-// This function assumes the operation is always ADD.
-std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
- float outputValue = 1.0f + static_cast<float>(len);
- return {{.operands = {
- // Input
- {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}},
- // Output
- {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}};
-}
+constexpr auto get_test_model = ::generated_tests::mobilenet_224_gender_basic_fixed::get_test_model;
} // namespace float32_model
namespace quant8_model {
-constexpr auto createTestModel = ::android::hardware::neuralnetworks::V1_2::generated_tests::
- mobilenet_quantized::createTestModel;
-constexpr auto get_examples = ::generated_tests::mobilenet_quantized::get_examples;
-
-// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
-// This function assumes the operation is always ADD.
-std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
- uint8_t outputValue = 1 + static_cast<uint8_t>(len);
- return {{.operands = {// Input
- {.operandDimensions = {{0, {1}}}, .quant8AsymmOperands = {{0, {1}}}},
- // Output
- {.operandDimensions = {{0, {1}}},
- .quant8AsymmOperands = {{0, {outputValue}}}}}}};
-}
+constexpr auto get_test_model = ::generated_tests::mobilenet_quantized::get_test_model;
} // namespace quant8_model
@@ -155,39 +112,34 @@
// [1] [1] [1] [1]
//
// This function assumes the operation is either ADD or MUL.
-template <typename CppType, OperandType operandType>
-Model createLargeTestModelImpl(OperationType op, uint32_t len) {
- EXPECT_TRUE(op == OperationType::ADD || op == OperationType::MUL);
+template <typename CppType, TestOperandType operandType>
+TestModel createLargeTestModelImpl(TestOperationType op, uint32_t len) {
+ EXPECT_TRUE(op == TestOperationType::ADD || op == TestOperationType::MUL);
// Model operations and operands.
- std::vector<Operation> operations(len);
- std::vector<Operand> operands(len * 2 + 2);
-
- // The constant buffer pool. This contains the activation scalar, followed by the
- // per-operation constant operands.
- std::vector<uint8_t> operandValues(sizeof(int32_t) + len * sizeof(CppType));
+ std::vector<TestOperation> operations(len);
+ std::vector<TestOperand> operands(len * 2 + 2);
// The activation scalar, value = 0.
operands[0] = {
- .type = OperandType::INT32,
+ .type = TestOperandType::INT32,
.dimensions = {},
.numberOfConsumers = len,
.scale = 0.0f,
.zeroPoint = 0,
- .lifetime = OperandLifeTime::CONSTANT_COPY,
- .location = {.poolIndex = 0, .offset = 0, .length = sizeof(int32_t)},
+ .lifetime = TestOperandLifeTime::CONSTANT_COPY,
+ .data = TestBuffer::createFromVector<int32_t>({0}),
};
- memset(operandValues.data(), 0, sizeof(int32_t));
// The buffer value of the constant second operand. The logical value is always 1.0f.
CppType bufferValue;
// The scale of the first and second operand.
float scale1, scale2;
- if (operandType == OperandType::TENSOR_FLOAT32) {
+ if (operandType == TestOperandType::TENSOR_FLOAT32) {
bufferValue = 1.0f;
scale1 = 0.0f;
scale2 = 0.0f;
- } else if (op == OperationType::ADD) {
+ } else if (op == TestOperationType::ADD) {
bufferValue = 1;
scale1 = 1.0f;
scale2 = 1.0f;
@@ -211,9 +163,9 @@
.numberOfConsumers = 1,
.scale = scale1,
.zeroPoint = 0,
- .lifetime = (i == 0 ? OperandLifeTime::MODEL_INPUT
- : OperandLifeTime::TEMPORARY_VARIABLE),
- .location = {},
+ .lifetime = (i == 0 ? TestOperandLifeTime::MODEL_INPUT
+ : TestOperandLifeTime::TEMPORARY_VARIABLE),
+ .data = (i == 0 ? TestBuffer::createFromVector<CppType>({1}) : TestBuffer()),
};
// The second operation input, value = 1.
@@ -223,13 +175,9 @@
.numberOfConsumers = 1,
.scale = scale2,
.zeroPoint = 0,
- .lifetime = OperandLifeTime::CONSTANT_COPY,
- .location = {.poolIndex = 0,
- .offset = static_cast<uint32_t>(i * sizeof(CppType) + sizeof(int32_t)),
- .length = sizeof(CppType)},
+ .lifetime = TestOperandLifeTime::CONSTANT_COPY,
+ .data = TestBuffer::createFromVector<CppType>({bufferValue}),
};
- memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(CppType), &bufferValue,
- sizeof(CppType));
// The operation. All operations share the same activation scalar.
// The output operand is created as an input in the next iteration of the loop, in the case
@@ -242,6 +190,10 @@
};
}
+ // For TestOperationType::ADD, output = 1 + 1 * len = len + 1
+ // For TestOperationType::MUL, output = 1 * 1 ^ len = 1
+ CppType outputResult = static_cast<CppType>(op == TestOperationType::ADD ? len + 1u : 1u);
+
// The model output.
operands.back() = {
.type = operandType,
@@ -249,21 +201,16 @@
.numberOfConsumers = 0,
.scale = scale1,
.zeroPoint = 0,
- .lifetime = OperandLifeTime::MODEL_OUTPUT,
- .location = {},
+ .lifetime = TestOperandLifeTime::MODEL_OUTPUT,
+ .data = TestBuffer::createFromVector<CppType>({outputResult}),
};
- const std::vector<uint32_t> inputIndexes = {1};
- const std::vector<uint32_t> outputIndexes = {len * 2 + 1};
- const std::vector<hidl_memory> pools = {};
-
return {
- .operands = operands,
- .operations = operations,
- .inputIndexes = inputIndexes,
- .outputIndexes = outputIndexes,
- .operandValues = operandValues,
- .pools = pools,
+ .operands = std::move(operands),
+ .operations = std::move(operations),
+ .inputIndexes = {1},
+ .outputIndexes = {len * 2 + 1},
+ .isRelaxed = false,
};
}
@@ -332,40 +279,26 @@
// Model and examples creators. According to kOperandType, the following methods will return
// either float32 model/examples or the quant8 variant.
- Model createTestModel() {
+ TestModel createTestModel() {
if (kOperandType == OperandType::TENSOR_FLOAT32) {
- return float32_model::createTestModel();
+ return float32_model::get_test_model();
} else {
- return quant8_model::createTestModel();
+ return quant8_model::get_test_model();
}
}
- std::vector<MixedTypedExample> get_examples() {
+ TestModel createLargeTestModel(OperationType op, uint32_t len) {
if (kOperandType == OperandType::TENSOR_FLOAT32) {
- return float32_model::get_examples();
+ return createLargeTestModelImpl<float, TestOperandType::TENSOR_FLOAT32>(
+ static_cast<TestOperationType>(op), len);
} else {
- return quant8_model::get_examples();
- }
- }
-
- Model createLargeTestModel(OperationType op, uint32_t len) {
- if (kOperandType == OperandType::TENSOR_FLOAT32) {
- return createLargeTestModelImpl<float, OperandType::TENSOR_FLOAT32>(op, len);
- } else {
- return createLargeTestModelImpl<uint8_t, OperandType::TENSOR_QUANT8_ASYMM>(op, len);
- }
- }
-
- std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
- if (kOperandType == OperandType::TENSOR_FLOAT32) {
- return float32_model::getLargeModelExamples(len);
- } else {
- return quant8_model::getLargeModelExamples(len);
+ return createLargeTestModelImpl<uint8_t, TestOperandType::TENSOR_QUANT8_ASYMM>(
+ static_cast<TestOperationType>(op), len);
}
}
// See if the service can handle the model.
- bool isModelFullySupported(const V1_2::Model& model) {
+ bool isModelFullySupported(const Model& model) {
bool fullySupportsModel = false;
Return<void> supportedCall = device->getSupportedOperations_1_2(
model,
@@ -379,14 +312,13 @@
return fullySupportsModel;
}
- void saveModelToCache(const V1_2::Model& model, const hidl_vec<hidl_handle>& modelCache,
+ void saveModelToCache(const Model& model, const hidl_vec<hidl_handle>& modelCache,
const hidl_vec<hidl_handle>& dataCache,
sp<IPreparedModel>* preparedModel = nullptr) {
if (preparedModel != nullptr) *preparedModel = nullptr;
// Launch prepare model.
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
Return<ErrorStatus> prepareLaunchStatus =
device->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER, modelCache,
@@ -398,9 +330,8 @@
preparedModelCallback->wait();
ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE);
if (preparedModel != nullptr) {
- *preparedModel =
- V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
- .withDefault(nullptr);
+ *preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+ .withDefault(nullptr);
}
}
@@ -416,7 +347,7 @@
return false;
}
- bool checkEarlyTermination(const V1_2::Model& model) {
+ bool checkEarlyTermination(const Model& model) {
if (!isModelFullySupported(model)) {
LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
"prepare model that it does not support.";
@@ -433,7 +364,6 @@
sp<IPreparedModel>* preparedModel, ErrorStatus* status) {
// Launch prepare model from cache.
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
Return<ErrorStatus> prepareLaunchStatus = device->prepareModelFromCache(
modelCache, dataCache, cacheToken, preparedModelCallback);
@@ -447,7 +377,7 @@
// Retrieve prepared model.
preparedModelCallback->wait();
*status = preparedModelCallback->getStatus();
- *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+ *preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
.withDefault(nullptr);
}
@@ -482,8 +412,9 @@
TEST_P(CompilationCachingTest, CacheSavingAndRetrieval) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
sp<IPreparedModel> preparedModel = nullptr;
// Save the compilation to cache.
@@ -491,7 +422,7 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
// Retrieve preparedModel from cache.
@@ -516,15 +447,15 @@
}
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
}
TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
sp<IPreparedModel> preparedModel = nullptr;
// Save the compilation to cache.
@@ -545,7 +476,7 @@
write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)),
sizeof(dummyBytes));
}
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
// Retrieve preparedModel from cache.
@@ -579,15 +510,15 @@
}
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
}
TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
// Test with number of model cache files greater than mNumModelCache.
{
@@ -598,13 +529,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.pop_back();
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -625,13 +554,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache.push_back(tmp);
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -651,13 +578,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.pop_back();
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -678,13 +603,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache.push_back(tmp);
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -698,15 +621,16 @@
TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
// Save the compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
// Test with number of model cache files greater than mNumModelCache.
@@ -778,8 +702,9 @@
TEST_P(CompilationCachingTest, SaveToCacheInvalidNumFd) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
// Go through each handle in model cache, test with NumFd greater than 1.
for (uint32_t i = 0; i < mNumModelCache; i++) {
@@ -790,13 +715,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache[i].pop_back();
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -817,13 +740,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mModelCache[i].push_back(tmp);
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -843,13 +764,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache[i].pop_back();
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -870,13 +789,11 @@
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
mDataCache[i].push_back(tmp);
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -890,15 +807,16 @@
TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
// Save the compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
// Go through each handle in model cache, test with NumFd greater than 1.
@@ -970,8 +888,9 @@
TEST_P(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
@@ -983,13 +902,11 @@
createCacheHandles(mDataCache, dataCacheMode, &dataCache);
modelCacheMode[i] = AccessMode::READ_WRITE;
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -1008,13 +925,11 @@
createCacheHandles(mDataCache, dataCacheMode, &dataCache);
dataCacheMode[i] = AccessMode::READ_WRITE;
sp<IPreparedModel> preparedModel = nullptr;
- saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+ saveModelToCache(model, modelCache, dataCache, &preparedModel);
ASSERT_NE(preparedModel, nullptr);
// Execute and verify results.
- generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
- get_examples(),
- testModel.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModel,
+ /*testDynamicOutputShape=*/false);
// Check if prepareModelFromCache fails.
preparedModel = nullptr;
ErrorStatus status;
@@ -1028,8 +943,9 @@
TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
// Create test HIDL model and compile.
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
@@ -1038,7 +954,7 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
// Go through each handle in model cache, test with invalid access mode.
@@ -1106,12 +1022,14 @@
if (!mIsCachingSupported) return;
// Create test models and check if fully supported by the service.
- const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
- if (checkEarlyTermination(testModelMul)) return;
- const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
- if (checkEarlyTermination(testModelAdd)) return;
+ const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+ const Model modelMul = createModel(testModelMul);
+ if (checkEarlyTermination(modelMul)) return;
+ const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+ const Model modelAdd = createModel(testModelAdd);
+ if (checkEarlyTermination(modelAdd)) return;
- // Save the testModelMul compilation to cache.
+ // Save the modelMul compilation to cache.
auto modelCacheMul = mModelCache;
for (auto& cache : modelCacheMul) {
cache[0].append("_mul");
@@ -1120,15 +1038,15 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModelMul, modelCache, dataCache);
+ saveModelToCache(modelMul, modelCache, dataCache);
}
- // Use a different token for testModelAdd.
+ // Use a different token for modelAdd.
mToken[0]++;
// This test is probabilistic, so we run it multiple times.
for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
- // Save the testModelAdd compilation to cache.
+ // Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
@@ -1136,7 +1054,7 @@
// Spawn a thread to copy the cache content concurrently while saving to cache.
std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
- saveModelToCache(testModelAdd, modelCache, dataCache);
+ saveModelToCache(modelAdd, modelCache, dataCache);
thread.join();
}
@@ -1155,11 +1073,8 @@
ASSERT_EQ(preparedModel, nullptr);
} else {
ASSERT_NE(preparedModel, nullptr);
- generated_tests::EvaluatePreparedModel(
- preparedModel, [](int) { return false; },
- getLargeModelExamples(kLargeModelSize),
- testModelAdd.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModelAdd,
+ /*testDynamicOutputShape=*/false);
}
}
}
@@ -1169,12 +1084,14 @@
if (!mIsCachingSupported) return;
// Create test models and check if fully supported by the service.
- const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
- if (checkEarlyTermination(testModelMul)) return;
- const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
- if (checkEarlyTermination(testModelAdd)) return;
+ const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+ const Model modelMul = createModel(testModelMul);
+ if (checkEarlyTermination(modelMul)) return;
+ const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+ const Model modelAdd = createModel(testModelAdd);
+ if (checkEarlyTermination(modelAdd)) return;
- // Save the testModelMul compilation to cache.
+ // Save the modelMul compilation to cache.
auto modelCacheMul = mModelCache;
for (auto& cache : modelCacheMul) {
cache[0].append("_mul");
@@ -1183,20 +1100,20 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModelMul, modelCache, dataCache);
+ saveModelToCache(modelMul, modelCache, dataCache);
}
- // Use a different token for testModelAdd.
+ // Use a different token for modelAdd.
mToken[0]++;
// This test is probabilistic, so we run it multiple times.
for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
- // Save the testModelAdd compilation to cache.
+ // Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModelAdd, modelCache, dataCache);
+ saveModelToCache(modelAdd, modelCache, dataCache);
}
// Retrieve preparedModel from cache.
@@ -1218,11 +1135,8 @@
ASSERT_EQ(preparedModel, nullptr);
} else {
ASSERT_NE(preparedModel, nullptr);
- generated_tests::EvaluatePreparedModel(
- preparedModel, [](int) { return false; },
- getLargeModelExamples(kLargeModelSize),
- testModelAdd.relaxComputationFloat32toFloat16,
- /*testDynamicOutputShape=*/false);
+ EvaluatePreparedModel(preparedModel, testModelAdd,
+ /*testDynamicOutputShape=*/false);
}
}
}
@@ -1232,12 +1146,14 @@
if (!mIsCachingSupported) return;
// Create test models and check if fully supported by the service.
- const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
- if (checkEarlyTermination(testModelMul)) return;
- const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
- if (checkEarlyTermination(testModelAdd)) return;
+ const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+ const Model modelMul = createModel(testModelMul);
+ if (checkEarlyTermination(modelMul)) return;
+ const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+ const Model modelAdd = createModel(testModelAdd);
+ if (checkEarlyTermination(modelAdd)) return;
- // Save the testModelMul compilation to cache.
+ // Save the modelMul compilation to cache.
auto modelCacheMul = mModelCache;
for (auto& cache : modelCacheMul) {
cache[0].append("_mul");
@@ -1246,21 +1162,21 @@
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModelMul, modelCache, dataCache);
+ saveModelToCache(modelMul, modelCache, dataCache);
}
- // Use a different token for testModelAdd.
+ // Use a different token for modelAdd.
mToken[0]++;
- // Save the testModelAdd compilation to cache.
+ // Save the modelAdd compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModelAdd, modelCache, dataCache);
+ saveModelToCache(modelAdd, modelCache, dataCache);
}
- // Replace the model cache of testModelAdd with testModelMul.
+ // Replace the model cache of modelAdd with modelMul.
copyCacheFiles(modelCacheMul, mModelCache);
// Retrieve the preparedModel from cache, expect failure.
@@ -1336,15 +1252,16 @@
// The modifier accepts one pointer argument "skip" as the returning value, indicating
// whether the test should be skipped or not.
void testCorruptedCache(ExpectedResult expected, std::function<void(bool*)> modifier) {
- const Model testModel = createTestModel();
- if (checkEarlyTermination(testModel)) return;
+ const TestModel& testModel = createTestModel();
+ const Model model = createModel(testModel);
+ if (checkEarlyTermination(model)) return;
// Save the compilation to cache.
{
hidl_vec<hidl_handle> modelCache, dataCache;
createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
- saveModelToCache(testModel, modelCache, dataCache);
+ saveModelToCache(model, modelCache, dataCache);
}
bool skip = false;
@@ -1424,9 +1341,4 @@
INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
::testing::Combine(kOperandTypeChoices, ::testing::Range(0U, 10U)));
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index 82cc73d..b8ca080 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -31,7 +31,10 @@
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
+#include <gtest/gtest.h>
+#include <algorithm>
#include <iostream>
+#include <numeric>
#include "1.0/Utils.h"
#include "1.2/Callbacks.h"
@@ -39,50 +42,135 @@
#include "MemoryUtils.h"
#include "TestHarness.h"
#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::ErrorStatus;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::android::hardware::neuralnetworks::V1_1::ExecutionPreference;
-using ::android::hardware::neuralnetworks::V1_2::Constant;
-using ::android::hardware::neuralnetworks::V1_2::IDevice;
-using ::android::hardware::neuralnetworks::V1_2::IPreparedModel;
-using ::android::hardware::neuralnetworks::V1_2::MeasureTiming;
-using ::android::hardware::neuralnetworks::V1_2::Model;
-using ::android::hardware::neuralnetworks::V1_2::OutputShape;
-using ::android::hardware::neuralnetworks::V1_2::Timing;
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using ::test_helper::compare;
-using ::test_helper::expectMultinomialDistributionWithinTolerance;
-using ::test_helper::filter;
-using ::test_helper::for_all;
-using ::test_helper::for_each;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExample;
-using ::test_helper::resize_accordingly;
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using implementation::ExecutionCallback;
+using implementation::PreparedModelCallback;
+using V1_0::DataLocation;
+using V1_0::ErrorStatus;
+using V1_0::OperandLifeTime;
+using V1_0::Request;
+using V1_1::ExecutionPreference;
using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
-static bool isZeroSized(const MixedTyped& example, uint32_t index) {
- for (auto i : example.operandDimensions.at(index)) {
- if (i == 0) return true;
+enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
+
+Model createModel(const TestModel& testModel) {
+ // Model operands.
+ hidl_vec<Operand> operands(testModel.operands.size());
+ size_t constCopySize = 0, constRefSize = 0;
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+
+ DataLocation loc = {};
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constCopySize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constCopySize += op.data.alignedSize();
+ } else if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ loc = {.poolIndex = 0,
+ .offset = static_cast<uint32_t>(constRefSize),
+ .length = static_cast<uint32_t>(op.data.size())};
+ constRefSize += op.data.alignedSize();
+ }
+
+ Operand::ExtraParams extraParams;
+ if (op.type == TestOperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
+ extraParams.channelQuant(SymmPerChannelQuantParams{
+ .scales = op.channelQuant.scales, .channelDim = op.channelQuant.channelDim});
+ }
+
+ operands[i] = {.type = static_cast<OperandType>(op.type),
+ .dimensions = op.dimensions,
+ .numberOfConsumers = op.numberOfConsumers,
+ .scale = op.scale,
+ .zeroPoint = op.zeroPoint,
+ .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+ .location = loc,
+ .extraParams = std::move(extraParams)};
}
- return false;
+
+ // Model operations.
+ hidl_vec<Operation> operations(testModel.operations.size());
+ std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
+ [](const TestOperation& op) -> Operation {
+ return {.type = static_cast<OperationType>(op.type),
+ .inputs = op.inputs,
+ .outputs = op.outputs};
+ });
+
+ // Constant copies.
+ hidl_vec<uint8_t> operandValues(constCopySize);
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, operandValues.data() + operands[i].location.offset);
+ }
+ }
+
+ // Shared memory.
+ hidl_vec<hidl_memory> pools = {};
+ if (constRefSize > 0) {
+ hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+ CHECK_NE(pools[0].size(), 0u);
+
+ // load data
+ sp<IMemory> mappedMemory = mapMemory(pools[0]);
+ CHECK(mappedMemory.get() != nullptr);
+ uint8_t* mappedPtr =
+ reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
+ CHECK(mappedPtr != nullptr);
+
+ for (uint32_t i = 0; i < testModel.operands.size(); i++) {
+ const auto& op = testModel.operands[i];
+ if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
+ const uint8_t* begin = op.data.get<uint8_t>();
+ const uint8_t* end = begin + op.data.size();
+ std::copy(begin, end, mappedPtr + operands[i].location.offset);
+ }
+ }
+ }
+
+ return {.operands = std::move(operands),
+ .operations = std::move(operations),
+ .inputIndexes = testModel.inputIndexes,
+ .outputIndexes = testModel.outputIndexes,
+ .operandValues = std::move(operandValues),
+ .pools = std::move(pools),
+ .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
}
-static Return<ErrorStatus> ExecutePreparedModel(sp<IPreparedModel>& preparedModel,
+static bool isOutputSizeGreaterThanOne(const TestModel& testModel, uint32_t index) {
+ const auto byteSize = testModel.operands[testModel.outputIndexes[index]].data.size();
+ return byteSize > 1u;
+}
+
+static void makeOutputInsufficientSize(uint32_t outputIndex, Request* request) {
+ auto& length = request->outputs[outputIndex].location.length;
+ ASSERT_GT(length, 1u);
+ length -= 1u;
+}
+
+static void makeOutputDimensionsUnspecified(Model* model) {
+ for (auto i : model->outputIndexes) {
+ auto& dims = model->operands[i].dimensions;
+ std::fill(dims.begin(), dims.end(), 0);
+ }
+}
+
+static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
const Request& request, MeasureTiming measure,
sp<ExecutionCallback>& callback) {
return preparedModel->execute_1_2(request, measure, callback);
}
-static Return<ErrorStatus> ExecutePreparedModel(sp<IPreparedModel>& preparedModel,
+static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
const Request& request, MeasureTiming measure,
hidl_vec<OutputShape>* outputShapes,
Timing* timing) {
@@ -105,294 +193,168 @@
return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
}
enum class Executor { ASYNC, SYNC, BURST };
-enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
-const float kDefaultAtol = 1e-5f;
-const float kDefaultRtol = 1e-5f;
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
+
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
Executor executor, MeasureTiming measure, OutputType outputType) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
+ // If output0 does not have size larger than one byte, we can not test with insufficient buffer.
+ if (outputType == OutputType::INSUFFICIENT && !isOutputSizeGreaterThanOne(testModel, 0)) {
+ return;
+ }
- int example_no = 1;
- for (auto& example : examples) {
- SCOPED_TRACE(example_no++);
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& golden = example.operands.second;
+ Request request = createRequest(testModel);
+ if (outputType == OutputType::INSUFFICIENT) {
+ makeOutputInsufficientSize(/*outputIndex=*/0, &request);
+ }
- const bool hasFloat16Inputs = !inputs.float16Operands.empty();
- if (hasRelaxedFloat32Model || hasFloat16Inputs) {
- // TODO: Adjust the error limit based on testing.
- // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
- fpAtol = 5.0f * 0.0009765625f;
- // Set the relative tolerance to be 5ULP of the corresponding FP precision.
- fpRtol = 5.0f * 0.0009765625f;
+ ErrorStatus executionStatus;
+ hidl_vec<OutputShape> outputShapes;
+ Timing timing;
+ switch (executor) {
+ case Executor::ASYNC: {
+ SCOPED_TRACE("asynchronous");
+
+ // launch execution
+ sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+ Return<ErrorStatus> executionLaunchStatus =
+ ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+ ASSERT_TRUE(executionLaunchStatus.isOk());
+ EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+ // retrieve execution status
+ executionCallback->wait();
+ executionStatus = executionCallback->getStatus();
+ outputShapes = executionCallback->getOutputShapes();
+ timing = executionCallback->getTiming();
+
+ break;
}
+ case Executor::SYNC: {
+ SCOPED_TRACE("synchronous");
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
+ // execute
+ Return<ErrorStatus> executionReturnStatus =
+ ExecutePreparedModel(preparedModel, request, measure, &outputShapes, &timing);
+ ASSERT_TRUE(executionReturnStatus.isOk());
+ executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+
+ break;
+ }
+ case Executor::BURST: {
+ SCOPED_TRACE("burst");
+
+ // create burst
+ const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
+ CreateBurst(preparedModel);
+ ASSERT_NE(nullptr, controller.get());
+
+ // create memory keys
+ std::vector<intptr_t> keys(request.pools.size());
+ for (size_t i = 0; i < keys.size(); ++i) {
+ keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
}
- }
- MixedTyped test; // holding test results
+ // execute burst
+ std::tie(executionStatus, outputShapes, timing) =
+ controller->compute(request, measure, keys);
- // Go through all outputs, initialize RequestArgument descriptors
- resize_accordingly(golden, test);
- bool sizeLargerThanOne = true;
- for_all(golden, [&golden, &outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
- int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- if (index == 0) {
- // On OutputType::INSUFFICIENT, set the output operand with index 0 with
- // buffer size one byte less than needed.
- if (outputType == OutputType::INSUFFICIENT) {
- if (s > 1 && !isZeroSized(golden, index)) {
- s -= 1;
- } else {
- sizeLargerThanOne = false;
- }
- }
- }
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // If output0 does not have size larger than one byte,
- // we can not provide an insufficient buffer
- if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- ASSERT_NE(0ull, pools[INPUT].size());
- ASSERT_NE(0ull, pools[OUTPUT].size());
-
- // load data
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
- ASSERT_NE(nullptr, inputMemory.get());
- ASSERT_NE(nullptr, outputMemory.get());
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
- ASSERT_NE(nullptr, inputPtr);
- ASSERT_NE(nullptr, outputPtr);
- inputMemory->update();
- outputMemory->update();
-
- // Go through all inputs, copy the values
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
-
- inputMemory->commit();
- outputMemory->commit();
-
- const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
-
- ErrorStatus executionStatus;
- hidl_vec<OutputShape> outputShapes;
- Timing timing;
- switch (executor) {
- case Executor::ASYNC: {
- SCOPED_TRACE("asynchronous");
-
- // launch execution
- sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
- Return<ErrorStatus> executionLaunchStatus =
- ExecutePreparedModel(preparedModel, request, measure, executionCallback);
- ASSERT_TRUE(executionLaunchStatus.isOk());
- EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
-
- // retrieve execution status
- executionCallback->wait();
- executionStatus = executionCallback->getStatus();
- outputShapes = executionCallback->getOutputShapes();
- timing = executionCallback->getTiming();
-
- break;
- }
- case Executor::SYNC: {
- SCOPED_TRACE("synchronous");
-
- // execute
- Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
- preparedModel, request, measure, &outputShapes, &timing);
- ASSERT_TRUE(executionReturnStatus.isOk());
- executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
-
- break;
- }
- case Executor::BURST: {
- SCOPED_TRACE("burst");
-
- // create burst
- const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
- CreateBurst(preparedModel);
- ASSERT_NE(nullptr, controller.get());
-
- // create memory keys
- std::vector<intptr_t> keys(request.pools.size());
- for (size_t i = 0; i < keys.size(); ++i) {
- keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
- }
-
- // execute burst
- std::tie(executionStatus, outputShapes, timing) =
- controller->compute(request, measure, keys);
-
- break;
- }
- }
-
- if (outputType != OutputType::FULLY_SPECIFIED &&
- executionStatus == ErrorStatus::GENERAL_FAILURE) {
- LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
- "execute model that it does not support.";
- std::cout << "[ ] Early termination of test because vendor service cannot "
- "execute model that it does not support."
- << std::endl;
- GTEST_SKIP();
- }
- if (measure == MeasureTiming::NO) {
- EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
- EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
- } else {
- if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
- EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
- }
- }
-
- switch (outputType) {
- case OutputType::FULLY_SPECIFIED:
- // If the model output operands are fully specified, outputShapes must be either
- // either empty, or have the same number of elements as the number of outputs.
- ASSERT_EQ(ErrorStatus::NONE, executionStatus);
- ASSERT_TRUE(outputShapes.size() == 0 ||
- outputShapes.size() == test.operandDimensions.size());
- break;
- case OutputType::UNSPECIFIED:
- // If the model output operands are not fully specified, outputShapes must have
- // the same number of elements as the number of outputs.
- ASSERT_EQ(ErrorStatus::NONE, executionStatus);
- ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
- break;
- case OutputType::INSUFFICIENT:
- ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
- ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
- ASSERT_FALSE(outputShapes[0].isSufficient);
- return;
- }
- // Go through all outputs, overwrite output dimensions with returned output shapes
- if (outputShapes.size() > 0) {
- for_each<uint32_t>(test.operandDimensions,
- [&outputShapes](int idx, std::vector<uint32_t>& dim) {
- dim = outputShapes[idx].dimensions;
- });
- }
-
- // validate results
- outputMemory->read();
- copy_back(&test, outputs_info, outputPtr);
- outputMemory->commit();
- // Filter out don't cares
- MixedTyped filtered_golden = filter(golden, is_ignored);
- MixedTyped filtered_test = filter(test, is_ignored);
-
- // We want "close-enough" results for float
- compare(filtered_golden, filtered_test, fpAtol, fpRtol);
-
- if (example.expectedMultinomialDistributionTolerance > 0) {
- expectMultinomialDistributionWithinTolerance(test, example);
+ break;
}
}
-}
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
- OutputType outputType) {
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
- kDefaultRtol, executor, measure, outputType);
+
+ if (outputType != OutputType::FULLY_SPECIFIED &&
+ executionStatus == ErrorStatus::GENERAL_FAILURE) {
+ LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+ "execute model that it does not support.";
+ std::cout << "[ ] Early termination of test because vendor service cannot "
+ "execute model that it does not support."
+ << std::endl;
+ GTEST_SKIP();
+ }
+ if (measure == MeasureTiming::NO) {
+ EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
+ EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
+ } else {
+ if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
+ EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
+ }
+ }
+
+ switch (outputType) {
+ case OutputType::FULLY_SPECIFIED:
+ // If the model output operands are fully specified, outputShapes must be either
+ // either empty, or have the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_TRUE(outputShapes.size() == 0 ||
+ outputShapes.size() == testModel.outputIndexes.size());
+ break;
+ case OutputType::UNSPECIFIED:
+ // If the model output operands are not fully specified, outputShapes must have
+ // the same number of elements as the number of outputs.
+ ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+ break;
+ case OutputType::INSUFFICIENT:
+ ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+ ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+ ASSERT_FALSE(outputShapes[0].isSufficient);
+ return;
+ }
+
+ // Go through all outputs, check returned output shapes.
+ for (uint32_t i = 0; i < outputShapes.size(); i++) {
+ EXPECT_TRUE(outputShapes[i].isSufficient);
+ const auto& expect = testModel.operands[testModel.outputIndexes[i]].dimensions;
+ const std::vector<uint32_t> actual = outputShapes[i].dimensions;
+ EXPECT_EQ(expect, actual);
+ }
+
+ // Retrieve execution results.
+ const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+
+ // We want "close-enough" results.
+ checkResults(testModel, outputs);
}
-void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
+ bool testDynamicOutputShape) {
if (testDynamicOutputShape) {
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+ OutputType::UNSPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+ OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+ OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+ OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+ OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+ OutputType::INSUFFICIENT);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+ OutputType::INSUFFICIENT);
} else {
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
- EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
- Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+ OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+ OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+ OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+ OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+ OutputType::FULLY_SPECIFIED);
+ EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+ OutputType::FULLY_SPECIFIED);
}
}
@@ -411,7 +373,6 @@
// launch prepare model
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
@@ -438,21 +399,39 @@
ASSERT_NE(nullptr, preparedModel->get());
}
-void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
- bool testDynamicOutputShape) {
- Model model = create_model();
- sp<IPreparedModel> preparedModel = nullptr;
- PrepareModel(device, model, &preparedModel);
- if (preparedModel == nullptr) {
- GTEST_SKIP();
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {
+ protected:
+ void Execute(const TestModel& testModel, bool testDynamicOutputShape) {
+ Model model = createModel(testModel);
+ if (testDynamicOutputShape) {
+ makeOutputDimensionsUnspecified(&model);
+ }
+
+ sp<IPreparedModel> preparedModel = nullptr;
+ PrepareModel(device, model, &preparedModel);
+ if (preparedModel == nullptr) {
+ GTEST_SKIP();
+ }
+ EvaluatePreparedModel(preparedModel, testModel, testDynamicOutputShape);
}
- EvaluatePreparedModel(preparedModel, is_ignored, examples,
- model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
+};
+
+// Tag for the dynamic output shape tests
+class DynamicOutputShapeTest : public GeneratedTest {};
+
+TEST_P(GeneratedTest, Test) {
+ Execute(*mTestModel, /*testDynamicOutputShape=*/false);
}
-} // namespace generated_tests
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+TEST_P(DynamicOutputShapeTest, Test) {
+ Execute(*mTestModel, /*testDynamicOutputShape=*/true);
+}
+
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+ [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+INSTANTIATE_GENERATED_TEST(DynamicOutputShapeTest,
+ [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
index 0ecbe7e..cb01b91 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
@@ -23,31 +23,50 @@
#include <functional>
#include <vector>
#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace generated_tests {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-using ::test_helper::MixedTypedExample;
+class GeneratedTestBase
+ : public NeuralnetworksHidlTest,
+ public ::testing::WithParamInterface<test_helper::TestModelManager::TestParam> {
+ protected:
+ void SetUp() override {
+ NeuralnetworksHidlTest::SetUp();
+ ASSERT_NE(mTestModel, nullptr);
+ }
-void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
- sp<V1_2::IPreparedModel>* preparedModel);
+ const test_helper::TestModel* mTestModel = GetParam().second;
+};
-void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
- std::function<bool(int)> is_ignored,
- const std::vector<MixedTypedExample>& examples,
- bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter) \
+ INSTANTIATE_TEST_SUITE_P( \
+ TestGenerated, TestSuite, \
+ ::testing::ValuesIn(::test_helper::TestModelManager::get().getTestModels(filter)), \
+ [](const auto& info) { return info.param.first; })
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
- std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
- bool testDynamicOutputShape = false);
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {
+ protected:
+ void validateEverything(const Model& model, const V1_0::Request& request);
+ void validateFailure(const Model& model, const V1_0::Request& request);
-} // namespace generated_tests
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+ private:
+ void validateModel(const Model& model);
+ void validateRequest(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+ void validateRequestFailure(const sp<IPreparedModel>& preparedModel,
+ const V1_0::Request& request);
+ void validateBurst(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+};
+
+Model createModel(const ::test_helper::TestModel& testModel);
+
+void PrepareModel(const sp<IDevice>& device, const Model& model, sp<IPreparedModel>* preparedModel);
+
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel,
+ const ::test_helper::TestModel& testModel, bool testDynamicOutputShape);
+
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
#endif // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.h b/neuralnetworks/1.2/vts/functional/GeneratedTests.h
deleted file mode 100644
index 9842036..0000000
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-#include "GeneratedTestHarness.h"
-#include "MemoryUtils.h"
-#include "TestHarness.h"
-#include "Utils.h"
-#include "VtsHalNeuralnetworks.h"
-
-namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-
-std::vector<Request> createRequests(const std::vector<::test_helper::MixedTypedExample>& examples);
-
-} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
-
-namespace android::hardware::neuralnetworks::V1_2::generated_tests {
-
-using namespace ::android::hardware::neuralnetworks::V1_2::vts::functional;
-
-using ::android::hardware::neuralnetworks::V1_0::OperandLifeTime;
-using ::android::hardware::neuralnetworks::V1_0::Request;
-
-} // namespace android::hardware::neuralnetworks::V1_2::generated_tests
diff --git a/neuralnetworks/1.2/vts/functional/TestAssertions.cpp b/neuralnetworks/1.2/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..a0aa3c3
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/TestAssertions.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_2 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+ static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperandType, FLOAT32);
+CHECK_TEST_ENUM(OperandType, INT32);
+CHECK_TEST_ENUM(OperandType, UINT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_INT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_ASYMM);
+CHECK_TEST_ENUM(OperandType, BOOL);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT16_SYMM);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT16);
+CHECK_TEST_ENUM(OperandType, TENSOR_BOOL8);
+CHECK_TEST_ENUM(OperandType, FLOAT16);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM_PER_CHANNEL);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT16_ASYMM);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM);
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+CHECK_TEST_ENUM(OperationType, BATCH_TO_SPACE_ND);
+CHECK_TEST_ENUM(OperationType, DIV);
+CHECK_TEST_ENUM(OperationType, MEAN);
+CHECK_TEST_ENUM(OperationType, PAD);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_BATCH_ND);
+CHECK_TEST_ENUM(OperationType, SQUEEZE);
+CHECK_TEST_ENUM(OperationType, STRIDED_SLICE);
+CHECK_TEST_ENUM(OperationType, SUB);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE);
+CHECK_TEST_ENUM(OperationType, ABS);
+CHECK_TEST_ENUM(OperationType, ARGMAX);
+CHECK_TEST_ENUM(OperationType, ARGMIN);
+CHECK_TEST_ENUM(OperationType, AXIS_ALIGNED_BBOX_TRANSFORM);
+CHECK_TEST_ENUM(OperationType, BIDIRECTIONAL_SEQUENCE_LSTM);
+CHECK_TEST_ENUM(OperationType, BIDIRECTIONAL_SEQUENCE_RNN);
+CHECK_TEST_ENUM(OperationType, BOX_WITH_NMS_LIMIT);
+CHECK_TEST_ENUM(OperationType, CAST);
+CHECK_TEST_ENUM(OperationType, CHANNEL_SHUFFLE);
+CHECK_TEST_ENUM(OperationType, DETECTION_POSTPROCESSING);
+CHECK_TEST_ENUM(OperationType, EQUAL);
+CHECK_TEST_ENUM(OperationType, EXP);
+CHECK_TEST_ENUM(OperationType, EXPAND_DIMS);
+CHECK_TEST_ENUM(OperationType, GATHER);
+CHECK_TEST_ENUM(OperationType, GENERATE_PROPOSALS);
+CHECK_TEST_ENUM(OperationType, GREATER);
+CHECK_TEST_ENUM(OperationType, GREATER_EQUAL);
+CHECK_TEST_ENUM(OperationType, GROUPED_CONV_2D);
+CHECK_TEST_ENUM(OperationType, HEATMAP_MAX_KEYPOINT);
+CHECK_TEST_ENUM(OperationType, INSTANCE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LESS);
+CHECK_TEST_ENUM(OperationType, LESS_EQUAL);
+CHECK_TEST_ENUM(OperationType, LOG);
+CHECK_TEST_ENUM(OperationType, LOGICAL_AND);
+CHECK_TEST_ENUM(OperationType, LOGICAL_NOT);
+CHECK_TEST_ENUM(OperationType, LOGICAL_OR);
+CHECK_TEST_ENUM(OperationType, LOG_SOFTMAX);
+CHECK_TEST_ENUM(OperationType, MAXIMUM);
+CHECK_TEST_ENUM(OperationType, MINIMUM);
+CHECK_TEST_ENUM(OperationType, NEG);
+CHECK_TEST_ENUM(OperationType, NOT_EQUAL);
+CHECK_TEST_ENUM(OperationType, PAD_V2);
+CHECK_TEST_ENUM(OperationType, POW);
+CHECK_TEST_ENUM(OperationType, PRELU);
+CHECK_TEST_ENUM(OperationType, QUANTIZE);
+CHECK_TEST_ENUM(OperationType, QUANTIZED_16BIT_LSTM);
+CHECK_TEST_ENUM(OperationType, RANDOM_MULTINOMIAL);
+CHECK_TEST_ENUM(OperationType, REDUCE_ALL);
+CHECK_TEST_ENUM(OperationType, REDUCE_ANY);
+CHECK_TEST_ENUM(OperationType, REDUCE_MAX);
+CHECK_TEST_ENUM(OperationType, REDUCE_MIN);
+CHECK_TEST_ENUM(OperationType, REDUCE_PROD);
+CHECK_TEST_ENUM(OperationType, REDUCE_SUM);
+CHECK_TEST_ENUM(OperationType, ROI_ALIGN);
+CHECK_TEST_ENUM(OperationType, ROI_POOLING);
+CHECK_TEST_ENUM(OperationType, RSQRT);
+CHECK_TEST_ENUM(OperationType, SELECT);
+CHECK_TEST_ENUM(OperationType, SIN);
+CHECK_TEST_ENUM(OperationType, SLICE);
+CHECK_TEST_ENUM(OperationType, SPLIT);
+CHECK_TEST_ENUM(OperationType, SQRT);
+CHECK_TEST_ENUM(OperationType, TILE);
+CHECK_TEST_ENUM(OperationType, TOPK_V2);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, UNIDIRECTIONAL_SEQUENCE_LSTM);
+CHECK_TEST_ENUM(OperationType, UNIDIRECTIONAL_SEQUENCE_RNN);
+CHECK_TEST_ENUM(OperationType, RESIZE_NEAREST_NEIGHBOR);
+
+#undef CHECK_TEST_ENUM
+
+} // namespace android::hardware::neuralnetworks::V1_2
diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
index 4d6bdbb..844e879 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
@@ -21,23 +21,21 @@
#include "1.2/Callbacks.h"
#include "ExecutionBurstController.h"
#include "ExecutionBurstServer.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
#include <android-base/logging.h>
#include <cstring>
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-using ::android::nn::ExecutionBurstController;
-using ::android::nn::RequestChannelSender;
-using ::android::nn::ResultChannelReceiver;
-using ExecutionBurstCallback = ::android::nn::ExecutionBurstController::ExecutionBurstCallback;
+using nn::ExecutionBurstController;
+using nn::RequestChannelSender;
+using nn::ResultChannelReceiver;
+using V1_0::ErrorStatus;
+using V1_0::Request;
+using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
// This constant value represents the length of an FMQ that is large enough to
// return a result from a burst execution for all of the generated test cases.
@@ -239,7 +237,7 @@
///////////////////////// BURST VALIATION TESTS ////////////////////////////////////
static void validateBurstSerialization(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
+ const Request& request) {
// create burst
std::unique_ptr<RequestChannelSender> sender;
std::unique_ptr<ResultChannelReceiver> receiver;
@@ -250,35 +248,32 @@
ASSERT_NE(nullptr, receiver.get());
ASSERT_NE(nullptr, context.get());
- // validate each request
- for (const Request& request : requests) {
- // load memory into callback slots
- std::vector<intptr_t> keys;
- keys.reserve(request.pools.size());
- std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
- [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
- const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
+ // load memory into callback slots
+ std::vector<intptr_t> keys;
+ keys.reserve(request.pools.size());
+ std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
+ [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
+ const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
- // ensure slot std::numeric_limits<int32_t>::max() doesn't exist (for
- // subsequent slot validation testing)
- ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) {
- return slot != std::numeric_limits<int32_t>::max();
- }));
+ // ensure slot std::numeric_limits<int32_t>::max() doesn't exist (for
+ // subsequent slot validation testing)
+ ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) {
+ return slot != std::numeric_limits<int32_t>::max();
+ }));
- // serialize the request
- const auto serialized = ::android::nn::serialize(request, MeasureTiming::YES, slots);
+ // serialize the request
+ const auto serialized = ::android::nn::serialize(request, MeasureTiming::YES, slots);
- // validations
- removeDatumTest(sender.get(), receiver.get(), serialized);
- addDatumTest(sender.get(), receiver.get(), serialized);
- mutateDatumTest(sender.get(), receiver.get(), serialized);
- }
+ // validations
+ removeDatumTest(sender.get(), receiver.get(), serialized);
+ addDatumTest(sender.get(), receiver.get(), serialized);
+ mutateDatumTest(sender.get(), receiver.get(), serialized);
}
// This test validates that when the Result message size exceeds length of the
// result FMQ, the service instance gracefully fails and returns an error.
static void validateBurstFmqLength(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
+ const Request& request) {
// create regular burst
std::shared_ptr<ExecutionBurstController> controllerRegular;
ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(
@@ -291,35 +286,32 @@
preparedModel, kExecutionBurstChannelSmallLength, &controllerSmall));
ASSERT_NE(nullptr, controllerSmall.get());
- // validate each request
- for (const Request& request : requests) {
- // load memory into callback slots
- std::vector<intptr_t> keys(request.pools.size());
- for (size_t i = 0; i < keys.size(); ++i) {
- keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
- }
-
- // collect serialized result by running regular burst
- const auto [statusRegular, outputShapesRegular, timingRegular] =
- controllerRegular->compute(request, MeasureTiming::NO, keys);
-
- // skip test if regular burst output isn't useful for testing a failure
- // caused by having too small of a length for the result FMQ
- const std::vector<FmqResultDatum> serialized =
- ::android::nn::serialize(statusRegular, outputShapesRegular, timingRegular);
- if (statusRegular != ErrorStatus::NONE ||
- serialized.size() <= kExecutionBurstChannelSmallLength) {
- continue;
- }
-
- // by this point, execution should fail because the result channel isn't
- // large enough to return the serialized result
- const auto [statusSmall, outputShapesSmall, timingSmall] =
- controllerSmall->compute(request, MeasureTiming::NO, keys);
- EXPECT_NE(ErrorStatus::NONE, statusSmall);
- EXPECT_EQ(0u, outputShapesSmall.size());
- EXPECT_TRUE(badTiming(timingSmall));
+ // load memory into callback slots
+ std::vector<intptr_t> keys(request.pools.size());
+ for (size_t i = 0; i < keys.size(); ++i) {
+ keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
}
+
+ // collect serialized result by running regular burst
+ const auto [statusRegular, outputShapesRegular, timingRegular] =
+ controllerRegular->compute(request, MeasureTiming::NO, keys);
+
+ // skip test if regular burst output isn't useful for testing a failure
+ // caused by having too small of a length for the result FMQ
+ const std::vector<FmqResultDatum> serialized =
+ ::android::nn::serialize(statusRegular, outputShapesRegular, timingRegular);
+ if (statusRegular != ErrorStatus::NONE ||
+ serialized.size() <= kExecutionBurstChannelSmallLength) {
+ return;
+ }
+
+ // by this point, execution should fail because the result channel isn't
+ // large enough to return the serialized result
+ const auto [statusSmall, outputShapesSmall, timingSmall] =
+ controllerSmall->compute(request, MeasureTiming::NO, keys);
+ EXPECT_NE(ErrorStatus::NONE, statusSmall);
+ EXPECT_EQ(0u, outputShapesSmall.size());
+ EXPECT_TRUE(badTiming(timingSmall));
}
static bool isSanitized(const FmqResultDatum& datum) {
@@ -367,7 +359,7 @@
}
static void validateBurstSanitized(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
+ const Request& request) {
// create burst
std::unique_ptr<RequestChannelSender> sender;
std::unique_ptr<ResultChannelReceiver> receiver;
@@ -378,40 +370,32 @@
ASSERT_NE(nullptr, receiver.get());
ASSERT_NE(nullptr, context.get());
- // validate each request
- for (const Request& request : requests) {
- // load memory into callback slots
- std::vector<intptr_t> keys;
- keys.reserve(request.pools.size());
- std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
- [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
- const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
+ // load memory into callback slots
+ std::vector<intptr_t> keys;
+ keys.reserve(request.pools.size());
+ std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
+ [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
+ const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
- // send valid request
- ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots));
+ // send valid request
+ ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots));
- // receive valid result
- auto serialized = receiver->getPacketBlocking();
- ASSERT_TRUE(serialized.has_value());
+ // receive valid result
+ auto serialized = receiver->getPacketBlocking();
+ ASSERT_TRUE(serialized.has_value());
- // sanitize result
- ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized))
- << "The result serialized data is not properly sanitized";
- }
+ // sanitize result
+ ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized))
+ << "The result serialized data is not properly sanitized";
}
///////////////////////////// ENTRY POINT //////////////////////////////////
void ValidationTest::validateBurst(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
- ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, requests));
- ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, requests));
- ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, requests));
+ const Request& request) {
+ ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, request));
+ ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, request));
+ ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, request));
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 9e52c44..ea9aa4f 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -18,21 +18,15 @@
#include "1.0/Utils.h"
#include "1.2/Callbacks.h"
+#include "GeneratedTestHarness.h"
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
+using implementation::PreparedModelCallback;
+using V1_0::ErrorStatus;
using V1_0::OperandLifeTime;
using V1_1::ExecutionPreference;
-
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -53,7 +47,6 @@
SCOPED_TRACE(message + " [prepareModel_1_2]");
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus =
device->prepareModel_1_2(model, preference, hidl_vec<hidl_handle>(),
hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
@@ -691,8 +684,9 @@
for (int32_t preference : invalidExecutionPreferences) {
const std::string message =
"mutateExecutionPreferenceTest: preference " + std::to_string(preference);
- validate(device, message, model, [](Model*) {},
- static_cast<ExecutionPreference>(preference));
+ validate(
+ device, message, model, [](Model*) {},
+ static_cast<ExecutionPreference>(preference));
}
}
@@ -716,9 +710,4 @@
mutateExecutionPreferenceTest(device, model);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index cf5905f..684b433 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -16,31 +16,19 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
#include "1.0/Utils.h"
#include "1.2/Callbacks.h"
#include "ExecutionBurstController.h"
-#include "MemoryUtils.h"
+#include "GeneratedTestHarness.h"
#include "TestHarness.h"
#include "Utils.h"
#include "VtsHalNeuralnetworks.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-using ::android::hardware::neuralnetworks::V1_0::RequestArgument;
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using implementation::ExecutionCallback;
+using V1_0::ErrorStatus;
+using V1_0::Request;
///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -71,7 +59,6 @@
SCOPED_TRACE(message + " [execute_1_2]");
sp<ExecutionCallback> executionCallback = new ExecutionCallback();
- ASSERT_NE(nullptr, executionCallback.get());
Return<ErrorStatus> executeLaunchStatus =
preparedModel->execute_1_2(request, measure, executionCallback);
ASSERT_TRUE(executeLaunchStatus.isOk());
@@ -161,124 +148,23 @@
///////////////////////////// ENTRY POINT //////////////////////////////////
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
- const uint32_t INPUT = 0;
- const uint32_t OUTPUT = 1;
-
- std::vector<Request> requests;
-
- for (auto& example : examples) {
- const MixedTyped& inputs = example.operands.first;
- const MixedTyped& outputs = example.operands.second;
-
- std::vector<RequestArgument> inputs_info, outputs_info;
- uint32_t inputSize = 0, outputSize = 0;
-
- // This function only partially specifies the metadata (vector of RequestArguments).
- // The contents are copied over below.
- for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
- if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = INPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- RequestArgument arg_empty = {
- .hasNoValue = true,
- };
- inputs_info[index] = s ? arg : arg_empty;
- inputSize += s;
- });
- // Compute offset for inputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : inputs_info) {
- if (!i.hasNoValue) i.location.offset = offset;
- offset += i.location.length;
- }
- }
-
- // Go through all outputs, initialize RequestArgument descriptors
- for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
- if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
- RequestArgument arg = {
- .location = {.poolIndex = OUTPUT,
- .offset = 0,
- .length = static_cast<uint32_t>(s)},
- .dimensions = {},
- };
- outputs_info[index] = arg;
- outputSize += s;
- });
- // Compute offset for outputs 1 and so on
- {
- size_t offset = 0;
- for (auto& i : outputs_info) {
- i.location.offset = offset;
- offset += i.location.length;
- }
- }
- std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
- nn::allocateSharedMemory(outputSize)};
- if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
- return {};
- }
-
- // map pool
- sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
- if (inputMemory == nullptr) {
- return {};
- }
- char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
- if (inputPtr == nullptr) {
- return {};
- }
-
- // initialize pool
- inputMemory->update();
- for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
- char* begin = (char*)p;
- char* end = begin + s;
- // TODO: handle more than one input
- std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
- });
- inputMemory->commit();
-
- requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
- }
-
- return requests;
-}
-
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
- // validate each request
- for (const Request& request : requests) {
- removeInputTest(preparedModel, request);
- removeOutputTest(preparedModel, request);
- }
+void ValidationTest::validateRequest(const sp<IPreparedModel>& preparedModel,
+ const Request& request) {
+ removeInputTest(preparedModel, request);
+ removeOutputTest(preparedModel, request);
}
void ValidationTest::validateRequestFailure(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests) {
- for (const Request& request : requests) {
- SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
- Return<void> executeStatus = preparedModel->executeSynchronously(
- request, MeasureTiming::NO,
- [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes,
- const Timing& timing) {
- ASSERT_NE(ErrorStatus::NONE, error);
- EXPECT_EQ(outputShapes.size(), 0);
- EXPECT_TRUE(badTiming(timing));
- });
- ASSERT_TRUE(executeStatus.isOk());
- }
+ const Request& request) {
+ SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
+ Return<void> executeStatus = preparedModel->executeSynchronously(
+ request, MeasureTiming::NO,
+ [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+ ASSERT_NE(ErrorStatus::NONE, error);
+ EXPECT_EQ(outputShapes.size(), 0);
+ EXPECT_TRUE(badTiming(timing));
+ });
+ ASSERT_TRUE(executeStatus.isOk());
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
index bd24edc..ea9d684 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,20 +17,19 @@
#define LOG_TAG "neuralnetworks_hidl_hal_test"
#include "VtsHalNeuralnetworks.h"
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
#include <android-base/logging.h>
-#include "1.2/Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using implementation::PreparedModelCallback;
using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using V1_0::ErrorStatus;
+using V1_0::Request;
using V1_1::ExecutionPreference;
// internal helper function
@@ -51,7 +50,6 @@
// launch prepare model
sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
- ASSERT_NE(nullptr, preparedModelCallback.get());
Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
@@ -84,10 +82,6 @@
}
// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
// This has to return a "new" object because it is freed inside
// ::testing::AddGlobalTestEnvironment when the gtest is being torn down
@@ -100,14 +94,8 @@
}
// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
void NeuralnetworksHidlTest::SetUp() {
::testing::VtsHalHidlTargetTestBase::SetUp();
- device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
- NeuralnetworksHidlEnvironment::getInstance());
#ifdef PRESUBMIT_NOT_VTS
const std::string name =
@@ -122,11 +110,10 @@
}
void NeuralnetworksHidlTest::TearDown() {
- device = nullptr;
::testing::VtsHalHidlTargetTestBase::TearDown();
}
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
+void ValidationTest::validateEverything(const Model& model, const Request& request) {
validateModel(model);
// create IPreparedModel
@@ -136,11 +123,11 @@
return;
}
- validateRequests(preparedModel, requests);
- validateBurst(preparedModel, requests);
+ validateRequest(preparedModel, request);
+ validateBurst(preparedModel, request);
}
-void ValidationTest::validateFailure(const Model& model, const std::vector<Request>& requests) {
+void ValidationTest::validateFailure(const Model& model, const Request& request) {
// TODO: Should this always succeed?
// What if the invalid input is part of the model (i.e., a parameter).
validateModel(model);
@@ -151,21 +138,27 @@
return;
}
- validateRequestFailure(preparedModel, requests);
+ validateRequestFailure(preparedModel, request);
}
-sp<IPreparedModel> getPreparedModel_1_2(
- const sp<V1_2::implementation::PreparedModelCallback>& callback) {
+TEST_P(ValidationTest, Test) {
+ const Model model = createModel(*mTestModel);
+ const Request request = createRequest(*mTestModel);
+ if (mTestModel->expectFailure) {
+ validateFailure(model, request);
+ } else {
+ validateEverything(model, request);
+ }
+}
+
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+
+sp<IPreparedModel> getPreparedModel_1_2(const sp<implementation::PreparedModelCallback>& callback) {
sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
- return V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+ return IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
}
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index 90dfe25..4a6d33b 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -30,24 +30,14 @@
#include <vector>
#include "1.2/Callbacks.h"
+#include "TestHarness.h"
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-
-using V1_0::DeviceStatus;
-using V1_0::ErrorStatus;
-using V1_0::Request;
-
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
// A class for test environment setup
class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
- NeuralnetworksHidlEnvironment();
- ~NeuralnetworksHidlEnvironment() override;
+ NeuralnetworksHidlEnvironment() = default;
public:
static NeuralnetworksHidlEnvironment* getInstance();
@@ -59,47 +49,19 @@
DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
public:
- NeuralnetworksHidlTest();
- ~NeuralnetworksHidlTest() override;
+ NeuralnetworksHidlTest() = default;
void SetUp() override;
void TearDown() override;
protected:
- sp<IDevice> device;
+ const sp<IDevice> device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
+ NeuralnetworksHidlEnvironment::getInstance());
};
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
- protected:
- void validateEverything(const Model& model, const std::vector<Request>& requests);
- void validateFailure(const Model& model, const std::vector<Request>& requests);
-
- private:
- void validateModel(const Model& model);
- void validateRequests(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests);
- void validateRequestFailure(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests);
- void validateBurst(const sp<IPreparedModel>& preparedModel,
- const std::vector<Request>& requests);
-};
-
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
-
-// Tag for the dynamic output shape tests
-class DynamicOutputShapeTest : public NeuralnetworksHidlTest {};
-
// Utility function to get PreparedModel from callback and downcast to V1_2.
-sp<IPreparedModel> getPreparedModel_1_2(
- const sp<V1_2::implementation::PreparedModelCallback>& callback);
+sp<IPreparedModel> getPreparedModel_1_2(const sp<implementation::PreparedModelCallback>& callback);
-} // namespace functional
-} // namespace vts
-} // namespace V1_2
-} // namespace neuralnetworks
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::neuralnetworks::V1_2::vts::functional
namespace android::hardware::neuralnetworks::V1_0 {
diff --git a/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
index 2992c0c..bf4792c 100644
--- a/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
+++ b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
@@ -46,8 +46,6 @@
namespace android::hardware::neuralnetworks::V1_2::implementation {
-using V1_0::ErrorStatus;
-
/**
* The PreparedModelCallback class is used to receive the error status of
* preparing a model as well as the prepared model from a task executing
@@ -87,7 +85,8 @@
* @param preparedModel Returned model that has been prepared for execution,
* nullptr if the model was unable to be prepared.
*/
- Return<void> notify(ErrorStatus status, const sp<V1_0::IPreparedModel>& preparedModel) override;
+ Return<void> notify(V1_0::ErrorStatus status,
+ const sp<V1_0::IPreparedModel>& preparedModel) override;
/**
* IPreparedModelCallback::notify_1_2 marks the callback object with the
@@ -112,7 +111,7 @@
* @param preparedModel Returned model that has been prepared for execution,
* nullptr if the model was unable to be prepared.
*/
- Return<void> notify_1_2(ErrorStatus status,
+ Return<void> notify_1_2(V1_0::ErrorStatus status,
const sp<V1_2::IPreparedModel>& preparedModel) override;
/**
@@ -134,7 +133,7 @@
* - GENERAL_FAILURE if there is an unspecified error
* - INVALID_ARGUMENT if the input model is invalid
*/
- ErrorStatus getStatus() const;
+ V1_0::ErrorStatus getStatus() const;
/**
* Retrieves the model that has been prepared for execution from the
@@ -152,7 +151,7 @@
mutable std::mutex mMutex;
mutable std::condition_variable mCondition;
bool mNotified GUARDED_BY(mMutex) = false;
- ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
+ V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
sp<V1_0::IPreparedModel> mPreparedModel;
};
@@ -195,7 +194,7 @@
* enough to store the resultant values
* - INVALID_ARGUMENT if the input request is invalid
*/
- Return<void> notify(ErrorStatus status) override;
+ Return<void> notify(V1_0::ErrorStatus status) override;
/**
* IExecutionCallback::notify_1_2 marks the callback object with the results
@@ -230,11 +229,11 @@
* reported as UINT64_MAX. A driver may choose to report any time as
* UINT64_MAX, indicating that particular measurement is not available.
*/
- Return<void> notify_1_2(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+ Return<void> notify_1_2(V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) override;
// An overload of the latest notify interface to hide the version from ExecutionBuilder.
- Return<void> notify(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+ Return<void> notify(V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
const Timing& timing) {
return notify_1_2(status, outputShapes, timing);
}
@@ -264,7 +263,7 @@
* - INVALID_ARGUMENT if one of the input arguments to prepareModel is
* invalid
*/
- ErrorStatus getStatus() const;
+ V1_0::ErrorStatus getStatus() const;
/**
* Retrieves the output shapes returned from the asynchronous task launched
@@ -309,14 +308,14 @@
* object before any call to wait or get* return. It then enables all prior
* and future wait calls on the ExecutionCallback object to proceed.
*/
- void notifyInternal(ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes,
+ void notifyInternal(V1_0::ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes,
const Timing& timing);
// members
mutable std::mutex mMutex;
mutable std::condition_variable mCondition;
bool mNotified GUARDED_BY(mMutex) = false;
- ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
+ V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
std::vector<OutputShape> mOutputShapes = {};
Timing mTiming = {};
};
diff --git a/nfc/1.0/default/Android.bp b/nfc/1.0/default/Android.bp
index 3b53d16..9827edd 100644
--- a/nfc/1.0/default/Android.bp
+++ b/nfc/1.0/default/Android.bp
@@ -12,7 +12,6 @@
"libcutils",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.nfc@1.0",
],
}
@@ -33,7 +32,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.nfc@1.0",
],
diff --git a/power/1.0/default/Android.bp b/power/1.0/default/Android.bp
index 4f43b95..1d152ee 100644
--- a/power/1.0/default/Android.bp
+++ b/power/1.0/default/Android.bp
@@ -28,7 +28,6 @@
"liblog",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.power@1.0",
],
@@ -54,7 +53,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.power@1.0",
],
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
index 7a09639..0321da1 100644
--- a/power/stats/1.0/default/Android.bp
+++ b/power/stats/1.0/default/Android.bp
@@ -25,7 +25,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.power.stats@1.0",
diff --git a/power/stats/1.0/vts/functional/Android.bp b/power/stats/1.0/vts/functional/Android.bp
index 4f0b325..f564cbe 100644
--- a/power/stats/1.0/vts/functional/Android.bp
+++ b/power/stats/1.0/vts/functional/Android.bp
@@ -31,8 +31,6 @@
"liblog",
"libhidlbase",
"libfmq",
- "libhidltransport",
- "libhwbinder",
"libutils",
],
}
diff --git a/radio/1.2/default/Android.bp b/radio/1.2/default/Android.bp
index f8ff4c7..74fcf11 100644
--- a/radio/1.2/default/Android.bp
+++ b/radio/1.2/default/Android.bp
@@ -9,7 +9,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.radio@1.2",
@@ -29,7 +28,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.radio@1.2",
diff --git a/radio/1.4/vts/functional/radio_response.cpp b/radio/1.4/vts/functional/radio_response.cpp
index a849926..d0aae47 100644
--- a/radio/1.4/vts/functional/radio_response.cpp
+++ b/radio/1.4/vts/functional/radio_response.cpp
@@ -733,8 +733,8 @@
const RadioResponseInfo& info,
const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls) {
rspInfo = info;
- parent_v1_4.notify(info.serial);
currentCalls = calls;
+ parent_v1_4.notify(info.serial);
return Void();
}
diff --git a/radio/config/1.0/default/Android.bp b/radio/config/1.0/default/Android.bp
index f52335e..a0f4214 100644
--- a/radio/config/1.0/default/Android.bp
+++ b/radio/config/1.0/default/Android.bp
@@ -11,7 +11,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.radio.config@1.0",
diff --git a/renderscript/1.0/default/Android.bp b/renderscript/1.0/default/Android.bp
index d5d6d8d..4fa85c6 100644
--- a/renderscript/1.0/default/Android.bp
+++ b/renderscript/1.0/default/Android.bp
@@ -14,7 +14,6 @@
"libdl",
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.renderscript@1.0",
],
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index 2485b05..d5c1b23 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -11,7 +11,6 @@
"libbase",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.sensors@1.0",
],
static_libs: [
@@ -34,7 +33,6 @@
"libbase",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.sensors@1.0",
],
local_include_dirs: ["include/sensors"],
@@ -57,7 +55,6 @@
"libbase",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.sensors@1.0",
],
}
diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp
index 05a34bb..62c9487 100644
--- a/sensors/2.0/default/Android.bp
+++ b/sensors/2.0/default/Android.bp
@@ -30,7 +30,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
"liblog",
"libpower",
"libutils",
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
index cc20f91..1f9ae45 100644
--- a/soundtrigger/2.0/default/Android.bp
+++ b/soundtrigger/2.0/default/Android.bp
@@ -28,7 +28,6 @@
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"libhardware",
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
index 5851d63..b8d0407 100644
--- a/soundtrigger/2.1/default/Android.mk
+++ b/soundtrigger/2.1/default/Android.mk
@@ -29,7 +29,6 @@
libhardware \
libhidlbase \
libhidlmemory \
- libhidltransport \
liblog \
libutils \
android.hardware.soundtrigger@2.1 \
diff --git a/soundtrigger/2.2/default/Android.bp b/soundtrigger/2.2/default/Android.bp
index 78bb69f..db37c5b 100644
--- a/soundtrigger/2.2/default/Android.bp
+++ b/soundtrigger/2.2/default/Android.bp
@@ -22,7 +22,6 @@
],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libhidlmemory",
"libutils",
diff --git a/tests/bar/1.0/default/Android.bp b/tests/bar/1.0/default/Android.bp
index 8aa6135..8e3d072 100644
--- a/tests/bar/1.0/default/Android.bp
+++ b/tests/bar/1.0/default/Android.bp
@@ -13,8 +13,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/baz/1.0/default/Android.bp b/tests/baz/1.0/default/Android.bp
index 492e0b4..4096d47 100644
--- a/tests/baz/1.0/default/Android.bp
+++ b/tests/baz/1.0/default/Android.bp
@@ -9,8 +9,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/extension/light/2.0/default/Android.bp b/tests/extension/light/2.0/default/Android.bp
index dcac97c..d8d8dd5 100644
--- a/tests/extension/light/2.0/default/Android.bp
+++ b/tests/extension/light/2.0/default/Android.bp
@@ -27,7 +27,6 @@
shared_libs: [
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.light@2.0",
"android.hardware.tests.extension.light@2.0",
diff --git a/tests/foo/1.0/default/Android.bp b/tests/foo/1.0/default/Android.bp
index d9dfc69..48d6894 100644
--- a/tests/foo/1.0/default/Android.bp
+++ b/tests/foo/1.0/default/Android.bp
@@ -13,8 +13,6 @@
"libcutils",
"libfootest",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/foo/1.0/default/lib/Android.bp b/tests/foo/1.0/default/lib/Android.bp
index 2cc96c5..ba2081e 100644
--- a/tests/foo/1.0/default/lib/Android.bp
+++ b/tests/foo/1.0/default/lib/Android.bp
@@ -8,8 +8,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
],
static_libs: ["android.hardware.tests.foo@1.0"],
diff --git a/tests/hash/1.0/default/Android.bp b/tests/hash/1.0/default/Android.bp
index 6e6d6a8..410b759 100644
--- a/tests/hash/1.0/default/Android.bp
+++ b/tests/hash/1.0/default/Android.bp
@@ -8,8 +8,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/inheritance/1.0/default/Android.bp b/tests/inheritance/1.0/default/Android.bp
index 891355b..4a0c876 100644
--- a/tests/inheritance/1.0/default/Android.bp
+++ b/tests/inheritance/1.0/default/Android.bp
@@ -14,8 +14,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/libhwbinder/1.0/default/Android.bp b/tests/libhwbinder/1.0/default/Android.bp
index aad1e31..81022b8 100644
--- a/tests/libhwbinder/1.0/default/Android.bp
+++ b/tests/libhwbinder/1.0/default/Android.bp
@@ -9,8 +9,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/memory/1.0/default/Android.bp b/tests/memory/1.0/default/Android.bp
index 3f13634..0293953 100644
--- a/tests/memory/1.0/default/Android.bp
+++ b/tests/memory/1.0/default/Android.bp
@@ -22,9 +22,7 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
"libhidlmemory",
- "libhwbinder",
"liblog",
"libutils",
"android.hidl.memory@1.0",
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index 6c8be6c..e6408aa 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -26,8 +26,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
@@ -49,7 +47,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.tests.msgq@1.0"
@@ -68,8 +65,6 @@
"libcutils",
"libfmq",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/multithread/1.0/default/Android.bp b/tests/multithread/1.0/default/Android.bp
index a94ee3e..ff89938 100644
--- a/tests/multithread/1.0/default/Android.bp
+++ b/tests/multithread/1.0/default/Android.bp
@@ -9,8 +9,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/safeunion/1.0/default/Android.bp b/tests/safeunion/1.0/default/Android.bp
index fc2443e..759a49c 100644
--- a/tests/safeunion/1.0/default/Android.bp
+++ b/tests/safeunion/1.0/default/Android.bp
@@ -9,8 +9,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/safeunion/cpp/1.0/default/Android.bp b/tests/safeunion/cpp/1.0/default/Android.bp
index 210a639..618f295 100644
--- a/tests/safeunion/cpp/1.0/default/Android.bp
+++ b/tests/safeunion/cpp/1.0/default/Android.bp
@@ -8,8 +8,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/tests/trie/1.0/default/Android.bp b/tests/trie/1.0/default/Android.bp
index 948a8cb..4ca705c 100644
--- a/tests/trie/1.0/default/Android.bp
+++ b/tests/trie/1.0/default/Android.bp
@@ -9,8 +9,6 @@
"libbase",
"libcutils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"liblog",
"libutils",
],
diff --git a/thermal/1.0/default/Android.bp b/thermal/1.0/default/Android.bp
index 9d81474..194a9f8 100644
--- a/thermal/1.0/default/Android.bp
+++ b/thermal/1.0/default/Android.bp
@@ -27,7 +27,6 @@
"libcutils",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.thermal@1.0",
],
}
@@ -48,7 +47,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.thermal@1.0",
],
}
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index dab0d33..7b72694 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -27,7 +27,6 @@
shared_libs: [
"libbase",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.thermal@2.0",
"android.hardware.thermal@1.0",
diff --git a/tv/cec/1.0/default/Android.bp b/tv/cec/1.0/default/Android.bp
index 5fe731b..239a527 100644
--- a/tv/cec/1.0/default/Android.bp
+++ b/tv/cec/1.0/default/Android.bp
@@ -7,7 +7,6 @@
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libbase",
"libutils",
@@ -34,7 +33,6 @@
"libhardware_legacy",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.tv.cec@1.0",
],
@@ -58,7 +56,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.tv.cec@1.0",
],
}
diff --git a/tv/cec/1.0/default/HdmiCecMock.cpp b/tv/cec/1.0/default/HdmiCecMock.cpp
index eba8f95..219be86 100644
--- a/tv/cec/1.0/default/HdmiCecMock.cpp
+++ b/tv/cec/1.0/default/HdmiCecMock.cpp
@@ -77,6 +77,7 @@
if (message.body.size() == 0) {
return SendMessageResult::NACK;
}
+ sendMessageToFifo(message);
return SendMessageResult::SUCCESS;
}
@@ -88,6 +89,11 @@
if (callback != nullptr) {
mCallback = callback;
mCallback->linkToDeath(this, 0 /*cookie*/);
+
+ mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR);
+ mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR);
+ pthread_create(&mThreadId, NULL, __threadLoop, this);
+ pthread_setname_np(mThreadId, "hdmi_cec_loop");
}
return Void();
}
@@ -102,17 +108,8 @@
}
Return<void> HdmiCecMock::getPortInfo(getPortInfo_cb _hidl_cb) {
- vector<HdmiPortInfo> portInfos;
// TODO ready port info from device specific config
- portInfos.resize(mTotalPorts);
- for (int i = 0; i < mTotalPorts; ++i) {
- portInfos[i] = {.type = HdmiPortType::INPUT,
- .portId = static_cast<uint32_t>(i),
- .cecSupported = true,
- .arcSupported = (i == 0),
- .physicalAddress = static_cast<uint16_t>(i << 12)};
- }
- _hidl_cb(portInfos);
+ _hidl_cb(mPortInfo);
return Void();
}
@@ -140,13 +137,177 @@
return Void();
}
-Return<bool> HdmiCecMock::isConnected(int32_t portId __unused) {
+Return<bool> HdmiCecMock::isConnected(int32_t portId) {
// maintain port connection status and update on hotplug event
+ if (portId < mTotalPorts && portId >= 0) {
+ return mPortConnectionStatus[portId];
+ }
return false;
}
+void* HdmiCecMock::__threadLoop(void* user) {
+ HdmiCecMock* const self = static_cast<HdmiCecMock*>(user);
+ self->threadLoop();
+ return 0;
+}
+
+int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+ if (msgCount <= 0 || !buf) {
+ return 0;
+ }
+
+ int ret = -1;
+ /* maybe blocked at driver */
+ ret = read(mInputFile, buf, msgCount);
+ if (ret < 0) {
+ ALOGE("[halimp] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+int HdmiCecMock::sendMessageToFifo(const CecMessage& message) {
+ unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+ int ret = -1;
+
+ memset(msgBuf, 0, sizeof(msgBuf));
+ msgBuf[0] = ((static_cast<uint8_t>(message.initiator) & 0xf) << 4) |
+ (static_cast<uint8_t>(message.destination) & 0xf);
+
+ size_t length = std::min(static_cast<size_t>(message.body.size()),
+ static_cast<size_t>(MaxLength::MESSAGE_BODY));
+ for (size_t i = 0; i < length; ++i) {
+ msgBuf[i + 1] = static_cast<unsigned char>(message.body[i]);
+ }
+
+ // open the output pipe for writing outgoing cec message
+ mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY);
+ if (mOutputFile < 0) {
+ ALOGD("[halimp] file open failed for writing");
+ return -1;
+ }
+
+ // write message into the output pipe
+ ret = write(mOutputFile, msgBuf, length + 1);
+ close(mOutputFile);
+ if (ret < 0) {
+ ALOGE("[halimp] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret);
+ return -1;
+ }
+ return ret;
+}
+
+void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) {
+ char buf[64] = {};
+ int i, size = 0;
+ memset(buf, 0, sizeof(buf));
+ for (i = 0; i < len; i++) {
+ size += sprintf(buf + size, " %02x", msg_buf[i]);
+ }
+ ALOGD("[halimp] %s, msg:%s", __FUNCTION__, buf);
+}
+
+void HdmiCecMock::handleHotplugMessage(unsigned char* msgBuf) {
+ HotplugEvent hotplugEvent{.connected = ((msgBuf[3]) & 0xf) > 0,
+ .portId = static_cast<uint32_t>(msgBuf[0] & 0xf)};
+
+ if (hotplugEvent.portId >= mPortInfo.size()) {
+ ALOGD("[halimp] ignore hot plug message, id %x does not exist", hotplugEvent.portId);
+ return;
+ }
+
+ ALOGD("[halimp] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf), (msgBuf[3] & 0xf));
+ if (mPortInfo[hotplugEvent.portId].type == HdmiPortType::OUTPUT) {
+ mPhysicalAddress =
+ ((hotplugEvent.connected == 0) ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2])));
+ mPortInfo[hotplugEvent.portId].physicalAddress = mPhysicalAddress;
+ ALOGD("[halimp] hot plug physical address %x", mPhysicalAddress);
+ }
+
+ // todo update connection status
+
+ if (mCallback != nullptr) {
+ mCallback->onHotplugEvent(hotplugEvent);
+ }
+}
+
+void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int megSize) {
+ CecMessage message;
+ size_t length = std::min(static_cast<size_t>(megSize - 1),
+ static_cast<size_t>(MaxLength::MESSAGE_BODY));
+ message.body.resize(length);
+
+ for (size_t i = 0; i < length; ++i) {
+ message.body[i] = static_cast<uint8_t>(msgBuf[i + 1]);
+ ALOGD("[halimp] msg body %x", message.body[i]);
+ }
+
+ message.initiator = static_cast<CecLogicalAddress>((msgBuf[0] >> 4) & 0xf);
+ ALOGD("[halimp] msg init %x", message.initiator);
+ message.destination = static_cast<CecLogicalAddress>((msgBuf[0] >> 0) & 0xf);
+ ALOGD("[halimp] msg dest %x", message.destination);
+
+ // messageValidateAndHandle(&event);
+
+ if (mCallback != nullptr) {
+ mCallback->onCecMessage(message);
+ }
+}
+
+void HdmiCecMock::threadLoop() {
+ ALOGD("[halimp] threadLoop start.");
+ unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+ int r = -1;
+
+ // open the input pipe
+ while (mInputFile < 0) {
+ usleep(1000 * 1000);
+ mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY);
+ }
+ ALOGD("[halimp] file open ok, fd = %d.", mInputFile);
+
+ while (mCecThreadRun) {
+ if (!mOptionSystemCecControl) {
+ usleep(1000 * 1000);
+ continue;
+ }
+
+ memset(msgBuf, 0, sizeof(msgBuf));
+ // try to get a message from dev.
+ // echo -n -e '\x04\x83' >> /dev/cec
+ r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH);
+ if (r <= 1) {
+ // ignore received ping messages
+ continue;
+ }
+
+ printCecMsgBuf((const char*)msgBuf, r);
+
+ if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+ // the message is a hotplug event
+ handleHotplugMessage(msgBuf);
+ continue;
+ }
+
+ handleCecMessage(msgBuf, r);
+ }
+
+ ALOGD("[halimp] thread end.");
+ // mCecDevice.mExited = true;
+}
+
HdmiCecMock::HdmiCecMock() {
- ALOGE("Opening a virtual HAL for testing and virtual machine.");
+ ALOGE("[halimp] Opening a virtual HAL for testing and virtual machine.");
+ mCallback = nullptr;
+ mPortInfo.resize(mTotalPorts);
+ mPortConnectionStatus.resize(mTotalPorts);
+ mPortInfo[0] = {.type = HdmiPortType::OUTPUT,
+ .portId = static_cast<uint32_t>(0),
+ .cecSupported = true,
+ .arcSupported = false,
+ .physicalAddress = mPhysicalAddress};
+ mPortConnectionStatus[0] = false;
}
} // namespace implementation
diff --git a/tv/cec/1.0/default/HdmiCecMock.h b/tv/cec/1.0/default/HdmiCecMock.h
index b2f1113..0a708fa 100644
--- a/tv/cec/1.0/default/HdmiCecMock.h
+++ b/tv/cec/1.0/default/HdmiCecMock.h
@@ -49,6 +49,9 @@
using ::android::hardware::tv::cec::V1_0::Result;
using ::android::hardware::tv::cec::V1_0::SendMessageResult;
+#define CEC_MSG_IN_FIFO "/dev/cec_in_pipe"
+#define CEC_MSG_OUT_FIFO "/dev/cec_out_pipe"
+
struct HdmiCecMock : public IHdmiCec, public hidl_death_recipient {
HdmiCecMock();
// Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
@@ -71,21 +74,43 @@
}
void cec_set_option(int flag, int value);
+ void printCecMsgBuf(const char* msg_buf, int len);
+
+ private:
+ static void* __threadLoop(void* data);
+ void threadLoop();
+ int readMessageFromFifo(unsigned char* buf, int msgCount);
+ int sendMessageToFifo(const CecMessage& message);
+ void handleHotplugMessage(unsigned char* msgBuf);
+ void handleCecMessage(unsigned char* msgBuf, int length);
private:
sp<IHdmiCecCallback> mCallback;
+
// Variables for the virtual cec hal impl
uint16_t mPhysicalAddress = 0xFFFF;
vector<CecLogicalAddress> mLogicalAddresses;
int32_t mCecVersion = 0;
uint32_t mCecVendorId = 0;
+
// Port configuration
- int mTotalPorts = 4;
+ int mTotalPorts = 1;
+ hidl_vec<HdmiPortInfo> mPortInfo;
+ hidl_vec<bool> mPortConnectionStatus;
+
// CEC Option value
int mOptionWakeUp = 0;
int mOptionEnableCec = 0;
int mOptionSystemCecControl = 0;
int mOptionLanguage = 0;
+
+ // Testing variables
+ // Input file descriptor
+ int mInputFile;
+ // Output file descriptor
+ int mOutputFile;
+ bool mCecThreadRun = true;
+ pthread_t mThreadId = 0;
};
} // namespace implementation
} // namespace V1_0
diff --git a/tv/cec/2.0/default/Android.bp b/tv/cec/2.0/default/Android.bp
index 6e624e3..d3d5342 100644
--- a/tv/cec/2.0/default/Android.bp
+++ b/tv/cec/2.0/default/Android.bp
@@ -7,7 +7,6 @@
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libbase",
"libutils",
@@ -35,7 +34,6 @@
"libhardware_legacy",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.tv.cec@2.0",
],
diff --git a/tv/input/1.0/default/Android.bp b/tv/input/1.0/default/Android.bp
index 7c140a5..5f6b7e7 100644
--- a/tv/input/1.0/default/Android.bp
+++ b/tv/input/1.0/default/Android.bp
@@ -10,7 +10,6 @@
"liblog",
"libhardware",
"libhidlbase",
- "libhidltransport",
"libutils",
"android.hardware.audio.common@2.0",
"android.hardware.tv.input@1.0",
@@ -35,7 +34,6 @@
"libhardware_legacy",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.audio.common@2.0",
"android.hardware.tv.input@1.0",
],
diff --git a/tv/tuner/1.0/Android.bp b/tv/tuner/1.0/Android.bp
new file mode 100644
index 0000000..986518b
--- /dev/null
+++ b/tv/tuner/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.tv.tuner@1.0",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IDemux.hal",
+ "IDemuxCallback.hal",
+ "IDescrambler.hal",
+ "IFrontend.hal",
+ "IFrontendCallback.hal",
+ "ITuner.hal",
+ ],
+ interfaces: [
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+ gen_java_constants: true,
+}
diff --git a/tv/tuner/1.0/IDemux.hal b/tv/tuner/1.0/IDemux.hal
new file mode 100644
index 0000000..2d7b275
--- /dev/null
+++ b/tv/tuner/1.0/IDemux.hal
@@ -0,0 +1,184 @@
+package android.hardware.tv.tuner@1.0;
+
+import IDemuxCallback;
+
+/**
+ * Demultiplexer(Demux) takes a single multiplexed input and splits it into
+ * one or more output.
+ *
+ */
+interface IDemux {
+
+ /**
+ * Set a frontend resource as data input of the demux
+ *
+ * It is used by the client to specify a hardware frontend as data source of
+ * this demux instance. A demux instance can have only one data source.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ setFrontendDataSource(FrontendId frontendId) generates (Result result);
+
+ /**
+ * Add a filter to the demux
+ *
+ * It is used by the client to add a filter to the demux.
+ *
+ * @param type the type of the filter to be added.
+ * @param bufferSize the buffer size of the filter to be added. It's used to
+ * create a FMQ(Fast Message Queue) to hold data output from the filter.
+ * @param cb the callback for the filter to be used to send notifications
+ * back to the client.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ * @return filterId the ID of the newly added filter.
+ */
+ addFilter(DemuxFilterType type, uint32_t bufferSize, IDemuxCallback cb)
+ generates (Result result, DemuxFilterId filterId);
+
+ /**
+ * Get the descriptor of the filter's FMQ
+ *
+ * It is used by the client to get the descriptor of the filter's Fast
+ * Message Queue. The data in FMQ is filtered out from MPEG transport
+ * stream. The data is origanized to data blocks which may have
+ * different length. The length's information of one or multiple data blocks
+ * is sent to client throught DemuxFilterEvent.
+ *
+ * @param filterId the ID of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ * @return queue the descriptor of the filter's FMQ
+ */
+ getFilterQueueDesc(DemuxFilterId filterId)
+ generates (Result result, fmq_sync<uint8_t> queue);
+
+ /**
+ * Configure the filter.
+ *
+ * It is used by the client to configure the filter so that it can filter out
+ * intended data.
+ *
+ * @param filterId the ID of the filter.
+ * @param settings the settings of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ configureFilter(DemuxFilterId filterId, DemuxFilterSettings settings)
+ generates(Result result);
+
+ /**
+ * Start the filter.
+ *
+ * It is used by the client to ask the filter to start filterring data.
+ *
+ * @param filterId the ID of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ startFilter(DemuxFilterId filterId) generates (Result result);
+
+ /**
+ * Stop the filter.
+ *
+ * It is used by the client to ask the filter to stop filterring data.
+ * It won't discard the data already filtered out by the filter. The filter
+ * will be stopped and removed automatically if the demux is closed.
+ *
+ * @param filterId the ID of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ stopFilter(DemuxFilterId filterId) generates (Result result);
+
+ /**
+ * Flush the filter.
+ *
+ * It is used by the client to ask the filter to flush the data which is
+ * already produced but not consumed yet.
+ *
+ * @param filterId the ID of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ flushFilter(DemuxFilterId filterId) generates (Result result);
+
+ /**
+ * Remove a filter from the demux
+ *
+ * It is used by the client to remove a filter from the demux.
+ *
+ * @param filterId the ID of the removed filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for wrong filter ID.
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ removeFilter(DemuxFilterId filterId) generates (Result result);
+
+ /**
+ * Get hardware sync ID for audio and video.
+ *
+ * It is used by the client to get the hardware sync ID for audio and video.
+ *
+ * @param filterId the ID of the filter.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for a wrong filter ID.
+ * UNKNOWN_ERROR if failed for other reasons.
+ * @return avSyncHwId the id of hardware A/V sync.
+ */
+ getAvSyncHwId(DemuxFilterId filterId)
+ generates (Result result, AvSyncHwId avSyncHwId);
+
+ /**
+ * Get current time stamp to use for A/V sync
+ *
+ * It is used by the client to get current time stamp for A/V sync. HW is
+ * supported to increment and maintain current time stamp.
+ *
+ * @param avSyncHwId the hardware id of A/V sync.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_ARGUMENT if failed for a wrong hardware ID of A/V sync.
+ * UNKNOWN_ERROR if failed for other reasons.
+ * @return time the current time stamp of hardware A/V sync. The time stamp
+ * based on 90KHz has the same format as PTS (Presentation Time Stamp).
+ */
+ getAvSyncTime(AvSyncHwId avSyncHwId)
+ generates (Result result, uint64_t time);
+
+ /**
+ * Close the Demux instance
+ *
+ * It is used by the client to release the demux instance. HAL clear
+ * underneath resource. client mustn't access the instance any more.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ close() generates (Result result);
+};
+
diff --git a/tv/tuner/1.0/IDemuxCallback.hal b/tv/tuner/1.0/IDemuxCallback.hal
new file mode 100644
index 0000000..7efd2c3
--- /dev/null
+++ b/tv/tuner/1.0/IDemuxCallback.hal
@@ -0,0 +1,19 @@
+package android.hardware.tv.tuner@1.0;
+
+interface IDemuxCallback {
+ /**
+ * Notify the client that a new filter event happened.
+ *
+ * @param filterEvent a demux filter event.
+ */
+ oneway onFilterEvent(DemuxFilterEvent filterEvent);
+
+ /**
+ * Notify the client a new status of a demux filter.
+ *
+ * @param filterId the demux filter ID.
+ * @param status a new status of the demux filter.
+ */
+ oneway onFilterStatus(DemuxFilterId filterId, DemuxFilterStatus status);
+};
+
diff --git a/tv/tuner/1.0/IDescrambler.hal b/tv/tuner/1.0/IDescrambler.hal
new file mode 100644
index 0000000..d078657
--- /dev/null
+++ b/tv/tuner/1.0/IDescrambler.hal
@@ -0,0 +1,79 @@
+package android.hardware.tv.tuner@1.0;
+/**
+ * Descrambler is used to descramble input data.
+ *
+ */
+interface IDescrambler {
+ /**
+ * Set a demux as source of the descrambler
+ *
+ * It is used by the client to specify a demux as source of this
+ * descrambler. A descrambler instance can have only one source, and
+ * this method can be only called once.
+ *
+ * @param demuxId the id of the demux to be used as descrambler's source.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ setDemuxSource(DemuxId demuxId) generates (Result result);
+
+ /**
+ * Set a key token to link descrambler to a key slot
+ *
+ * It is used by the client to link a hardware key slot to a descrambler.
+ * A descrambler instance can have only one key slot to link, but a key
+ * slot can hold a few keys for different purposes.
+ *
+ * @param keyToken the token to be used to link the key slot.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ setKeyToken(TunerKeyToken keyToken) generates (Result result);
+
+ /**
+ * Add packets' PID to the descrambler for descrambling
+ *
+ * It is used by the client to specify Package ID (PID) of packets which the
+ * descrambler start to descramble. Multiple PIDs can be added into one
+ * descrambler instance because descambling can happen simultaneously on
+ * packets from different PIDs.
+ *
+ * @param pid the PID of packets to start to be descrambled.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ addPid(DemuxTpid pid) generates (Result result);
+
+ /**
+ * Remove packets' PID from the descrambler
+ *
+ * It is used by the client to specify Package ID (PID) of packets which the
+ * descrambler stop to descramble.
+ *
+ * @param pid the PID of packets to stop to be descrambled.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if failed for wrong state.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ removePid(DemuxTpid pid) generates (Result result);
+
+ /**
+ * Release the descrambler instance
+ *
+ * It is used by the client to release the descrambler instance. HAL clear
+ * underneath resource. client mustn't access the instance any more.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ close() generates (Result result);
+};
+
diff --git a/tv/tuner/1.0/IFrontend.hal b/tv/tuner/1.0/IFrontend.hal
new file mode 100644
index 0000000..05cee91
--- /dev/null
+++ b/tv/tuner/1.0/IFrontend.hal
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.tv.tuner@1.0;
+
+import IFrontendCallback;
+
+/**
+ * A Tuner Frontend is used to tune to a frequency and lock signal. It provide
+ * live data feed to Tuner Demux interface.
+ */
+interface IFrontend {
+ /**
+ * Set the callback
+ *
+ * It is used by the client to receive events from the Frontend.
+ * Only one callback for one Frontend instance is supported. The callback
+ * will be replaced if it's set again.
+ *
+ * @param callback Callback object to pass Frontend events to the system.
+ * The previously registered callback must be replaced with this one.
+ * It can be null.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if callback can't be set at current stage,
+ * UNKNOWN_ERROR if callback setting failed for other reasons.
+ */
+ setCallback(IFrontendCallback callback) generates (Result result);
+
+ /**
+ * Tuning Frontend
+ *
+ * It is used by the client to lock a frequency by providing signal
+ * delivery information. If previous tuning isn't completed, this call must
+ * stop previous tuning, and start a new tuning. Tune is a async call.
+ * LOCKED or NO_SIGNAL eventi is sent back to caller through callback.
+ *
+ * @param settings Signal delivery information which frontend can use to
+ * search and lock the signal.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if tuning can't be applied at current stage,
+ * UNKNOWN_ERROR if tuning failed for other reasons.
+ */
+ tune(FrontendSettings settings) generates (Result result);
+
+ /**
+ * Stop the tuning
+ *
+ * It is used by the client to stop a previous tuning.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successfully stop tuning.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ stopTune() generates (Result result);
+
+ /**
+ * Release the Frontend instance
+ *
+ * It is used by the client to release the frontend instance. HAL clear
+ * underneath resource. client mustn't access the instance any more.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ close() generates (Result result);
+};
diff --git a/tv/tuner/1.0/IFrontendCallback.hal b/tv/tuner/1.0/IFrontendCallback.hal
new file mode 100644
index 0000000..e907049
--- /dev/null
+++ b/tv/tuner/1.0/IFrontendCallback.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.0;
+
+interface IFrontendCallback {
+ /**
+ * Notify the client that a new event happened on the frontend.
+ *
+ * @param frontendEventType the event type.
+ */
+ oneway onEvent(FrontendEventType frontendEventType);
+
+ /**
+ * The callback function that must be called by HAL implementation to notify
+ * the client of new DiSEqC message.
+ *
+ * @param diseqcMessage a byte array of data for DiSEqC (Digital Satellite
+ * Equipment Control) message which is specified by EUTELSAT Bus Functional
+ * Specification Version 4.2.
+ */
+ oneway onDiseqcMessage(vec<uint8_t> diseqcMessage);
+};
+
diff --git a/tv/tuner/1.0/ITuner.hal b/tv/tuner/1.0/ITuner.hal
new file mode 100644
index 0000000..a0f3e8e
--- /dev/null
+++ b/tv/tuner/1.0/ITuner.hal
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.0;
+
+import IDemux;
+import IDescrambler;
+import IFrontend;
+
+/**
+ * Top level interface to manage Frontend, Demux and Decrambler hardware
+ * resouces which are needed for Android TV.
+ */
+interface ITuner {
+ /**
+ * Get Frontend IDs
+ *
+ * It is used by the client to get all available frontends' IDs.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if tuning failed for other reasons.
+ * @return frontendIds an array of FrontendId for the available frontends.
+ */
+ getFrontendIds() generates (Result result, vec<FrontendId> frontendIds);
+
+ /**
+ * Create a new instance of Frontend given a frontendId.
+ *
+ * It is used by the client to create a frontend instance.
+ *
+ * @param frontendId the id of the frontend to be opened.
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if creation failed for other reasons.
+ * @return frontend the newly created frontend interface.
+ */
+ openFrontendById(FrontendId frontendId)
+ generates (Result result, IFrontend frontend);
+
+ /**
+ * Create a new instance of Demux.
+ *
+ * It is used by the client to create a Demux instance.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if creation failed for other reasons.
+ * @return demuxId newly created demux id.
+ * @return demux the newly created demux interface.
+ */
+ openDemux()
+ generates (Result result, DemuxId demuxId, IDemux demux);
+
+ /**
+ * Create a new instance of Descrambler.
+ *
+ * It is used by the client to create a Descrambler instance.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if creation failed for other reasons.
+ * @return descrambler the newly created descrambler interface.
+ */
+ openDescrambler()
+ generates (Result result, IDescrambler descrambler);
+};
diff --git a/tv/tuner/1.0/default/Android.bp b/tv/tuner/1.0/default/Android.bp
new file mode 100644
index 0000000..b211dd2
--- /dev/null
+++ b/tv/tuner/1.0/default/Android.bp
@@ -0,0 +1,46 @@
+cc_defaults {
+ name: "tuner_service_defaults",
+ defaults: ["hidl_defaults"],
+ vendor: true,
+ relative_install_path: "hw",
+ srcs: [
+ "Frontend.cpp",
+ "Descrambler.cpp",
+ "Demux.cpp",
+ "Tuner.cpp",
+ "service.cpp",
+ ],
+
+ compile_multilib: "first",
+
+ shared_libs: [
+ "android.hardware.tv.tuner@1.0",
+ "android.hidl.memory@1.0",
+ "libcutils",
+ "libfmq",
+ "libhidlbase",
+ "libhidlmemory",
+ "liblog",
+ "libstagefright_foundation",
+ "libutils",
+ ],
+ header_libs: [
+ "media_plugin_headers",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.tv.tuner@1.0-service",
+ vintf_fragments: ["android.hardware.tv.tuner@1.0-service.xml"],
+ defaults: ["tuner_service_defaults"],
+ init_rc: ["android.hardware.tv.tuner@1.0-service.rc"],
+}
+
+cc_binary {
+ name: "android.hardware.tv.tuner@1.0-service-lazy",
+ vintf_fragments: ["android.hardware.tv.tuner@1.0-service-lazy.xml"],
+ overrides: ["android.hardware.tv.tuner@1.0-service"],
+ defaults: ["tuner_service_defaults"],
+ init_rc: ["android.hardware.tv.tuner@1.0-service-lazy.rc"],
+ cflags: ["-DLAZY_SERVICE"],
+}
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
new file mode 100644
index 0000000..4016c5a
--- /dev/null
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -0,0 +1,405 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.0-Demux"
+
+#include "Demux.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+#define WAIT_TIMEOUT 3000000000
+
+const std::vector<uint8_t> fakeDataInputBuffer{
+ 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+ 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+ 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+ 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+ 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+ 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+ 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+ 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+ 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
+ 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
+ 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
+ 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
+ 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
+ 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
+ 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
+ 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
+ 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
+ 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
+ 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
+ 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
+ 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
+ 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
+ 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
+ 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
+ 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
+ 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
+ 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
+ 0x73, 0x63, 0x65, 0x6e, 0x65,
+};
+
+Demux::Demux(uint32_t demuxId) {
+ mDemuxId = demuxId;
+}
+
+Demux::~Demux() {}
+
+bool Demux::createAndSaveMQ(uint32_t bufferSize, uint32_t filterId) {
+ ALOGV("%s", __FUNCTION__);
+
+ // Create a synchronized FMQ that supports blocking read/write
+ std::unique_ptr<FilterMQ> tmpFilterMQ =
+ std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
+ if (!tmpFilterMQ->isValid()) {
+ ALOGW("Failed to create FMQ of filter with id: %d", filterId);
+ return false;
+ }
+
+ mFilterMQs.resize(filterId + 1);
+ mFilterMQs[filterId] = std::move(tmpFilterMQ);
+
+ EventFlag* mFilterEventFlag;
+ if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &mFilterEventFlag) !=
+ OK) {
+ return false;
+ }
+ mFilterEventFlags.resize(filterId + 1);
+ mFilterEventFlags[filterId] = mFilterEventFlag;
+ mFilterWriteCount.resize(filterId + 1);
+ mFilterWriteCount[filterId] = 0;
+ mThreadRunning.resize(filterId + 1);
+
+ return true;
+}
+
+Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
+ ALOGV("%s", __FUNCTION__);
+
+ mSourceFrontendId = frontendId;
+
+ return Result::SUCCESS;
+}
+
+Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
+ const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ uint32_t filterId = mLastUsedFilterId + 1;
+ mLastUsedFilterId += 1;
+
+ if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
+ ALOGW("callback can't be null");
+ _hidl_cb(Result::INVALID_ARGUMENT, filterId);
+ return Void();
+ }
+ // Add callback
+ mDemuxCallbacks.resize(filterId + 1);
+ mDemuxCallbacks[filterId] = cb;
+
+ // Mapping from the filter ID to the filter type
+ mFilterTypes.resize(filterId + 1);
+ mFilterTypes[filterId] = type;
+
+ if (!createAndSaveMQ(bufferSize, filterId)) {
+ _hidl_cb(Result::UNKNOWN_ERROR, -1);
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, filterId);
+ return Void();
+}
+
+Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (filterId < 0 || filterId > mLastUsedFilterId) {
+ ALOGW("No filter with id: %d exists", filterId);
+ _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
+ return Void();
+}
+
+Return<Result> Demux::configureFilter(uint32_t /* filterId */,
+ const DemuxFilterSettings& /* settings */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::startFilter(uint32_t filterId) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (filterId < 0 || filterId > mLastUsedFilterId) {
+ ALOGW("No filter with id: %d exists", filterId);
+ return Result::INVALID_ARGUMENT;
+ }
+
+ DemuxFilterType filterType = mFilterTypes[filterId];
+ Result result;
+ DemuxFilterEvent event{
+ .filterId = filterId,
+ .filterType = filterType,
+ };
+
+ switch (filterType) {
+ case DemuxFilterType::SECTION:
+ result = startSectionFilterHandler(event);
+ break;
+ case DemuxFilterType::PES:
+ result = startPesFilterHandler(event);
+ break;
+ case DemuxFilterType::TS:
+ result = startTsFilterHandler();
+ return Result::SUCCESS;
+ case DemuxFilterType::AUDIO:
+ case DemuxFilterType::VIDEO:
+ result = startMediaFilterHandler(event);
+ break;
+ case DemuxFilterType::RECORD:
+ result = startRecordFilterHandler(event);
+ break;
+ case DemuxFilterType::PCR:
+ result = startPcrFilterHandler();
+ return Result::SUCCESS;
+ default:
+ return Result::UNKNOWN_ERROR;
+ }
+
+ return result;
+}
+
+Return<Result> Demux::stopFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::removeFilter(uint32_t /* filterId */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ AvSyncHwId avSyncHwId = 0;
+
+ _hidl_cb(Result::SUCCESS, avSyncHwId);
+ return Void();
+}
+
+Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ uint64_t avSyncTime = 0;
+
+ _hidl_cb(Result::SUCCESS, avSyncTime);
+ return Void();
+}
+
+Return<Result> Demux::close() {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+bool Demux::writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum) {
+ event.events.resize(sectionNum);
+ for (int i = 0; i < sectionNum; i++) {
+ DemuxFilterSectionEvent secEvent;
+ secEvent = {
+ // temp dump meta data
+ .tableId = 0,
+ .version = 1,
+ .sectionNum = 1,
+ .dataLength = 530,
+ };
+ event.events[i].section(secEvent);
+ if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
+ std::lock_guard<std::mutex> lock(mWriteLock);
+ if (mFilterMQs[filterId]->write(data.data(), data.size())) {
+ return true;
+ }
+ return false;
+}
+
+Result Demux::startSectionFilterHandler(DemuxFilterEvent event) {
+ struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
+ threadArgs->user = this;
+ threadArgs->event = &event;
+
+ pthread_create(&mThreadId, NULL, __threadLoop, (void*)threadArgs);
+ pthread_setname_np(mThreadId, "demux_filter_waiting_loop");
+
+ return Result::SUCCESS;
+}
+
+Result Demux::startPesFilterHandler(DemuxFilterEvent& event) {
+ // TODO generate multiple events in one event callback
+ DemuxFilterPesEvent pesEvent;
+ pesEvent = {
+ // temp dump meta data
+ .streamId = 0,
+ .dataLength = 530,
+ };
+ event.events.resize(1);
+ event.events[0].pes(pesEvent);
+ /*pthread_create(&mThreadId, NULL, __threadLoop, this);
+ pthread_setname_np(mThreadId, "demux_section_filter_waiting_loop");*/
+ if (!writeDataToFilterMQ(fakeDataInputBuffer, event.filterId)) {
+ return Result::INVALID_STATE;
+ }
+
+ if (mDemuxCallbacks[event.filterId] == nullptr) {
+ return Result::NOT_INITIALIZED;
+ }
+
+ mDemuxCallbacks[event.filterId]->onFilterEvent(event);
+ return Result::SUCCESS;
+}
+
+Result Demux::startTsFilterHandler() {
+ // TODO handle starting TS filter
+ return Result::SUCCESS;
+}
+
+Result Demux::startMediaFilterHandler(DemuxFilterEvent& event) {
+ DemuxFilterMediaEvent mediaEvent;
+ mediaEvent = {
+ // temp dump meta data
+ .pts = 0,
+ .dataLength = 530,
+ .secureMemory = nullptr,
+ };
+ event.events.resize(1);
+ event.events[0].media() = mediaEvent;
+ // TODO handle write FQM for media stream
+ return Result::SUCCESS;
+}
+
+Result Demux::startRecordFilterHandler(DemuxFilterEvent& event) {
+ DemuxFilterRecordEvent recordEvent;
+ recordEvent = {
+ // temp dump meta data
+ .tpid = 0,
+ .packetNum = 0,
+ };
+ recordEvent.indexMask.tsIndexMask() = 0x01;
+ event.events.resize(1);
+ event.events[0].ts() = recordEvent;
+ return Result::SUCCESS;
+}
+
+Result Demux::startPcrFilterHandler() {
+ // TODO handle starting PCR filter
+ return Result::SUCCESS;
+}
+
+void* Demux::__threadLoop(void* threadArg) {
+ Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
+ self->filterThreadLoop(((struct ThreadArgs*)threadArg)->event);
+ return 0;
+}
+
+void Demux::filterThreadLoop(DemuxFilterEvent* event) {
+ uint32_t filterId = event->filterId;
+ ALOGD("[Demux] filter %d threadLoop start.", filterId);
+ mThreadRunning[filterId] = true;
+
+ while (mThreadRunning[filterId]) {
+ uint32_t efState = 0;
+ // We do not wait for the last round of writen data to be read to finish the thread
+ // because the VTS can verify the reading itself.
+ for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
+ DemuxFilterEvent filterEvent{
+ .filterId = filterId,
+ .filterType = event->filterType,
+ };
+ if (!writeSectionsAndCreateEvent(filterEvent, 2)) {
+ ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
+ break;
+ }
+ mFilterWriteCount[filterId]++;
+ if (mDemuxCallbacks[filterId] == nullptr) {
+ ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
+ break;
+ }
+ // After successfully write, send a callback and wait for the read to be done
+ mDemuxCallbacks[filterId]->onFilterEvent(filterEvent);
+ // We do not wait for the last read to be done
+ // VTS can verify the read result itself.
+ if (i == SECTION_WRITE_COUNT - 1) {
+ ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
+ break;
+ }
+ while (mThreadRunning[filterId]) {
+ status_t status = mFilterEventFlags[filterId]->wait(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
+ WAIT_TIMEOUT, true /* retry on spurious wake */);
+ if (status != OK) {
+ ALOGD("[Demux] wait for data consumed");
+ continue;
+ }
+ break;
+ }
+ }
+
+ mFilterWriteCount[filterId] = 0;
+ mThreadRunning[filterId] = false;
+ }
+
+ ALOGD("[Demux] filter thread ended.");
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
new file mode 100644
index 0000000..8b00266
--- /dev/null
+++ b/tv/tuner/1.0/default/Demux.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
+
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <fmq/MessageQueue.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IDemuxCallback;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class Demux : public IDemux {
+ public:
+ Demux(uint32_t demuxId);
+
+ virtual Return<Result> setFrontendDataSource(uint32_t frontendId) override;
+
+ virtual Return<Result> close() override;
+
+ virtual Return<void> addFilter(DemuxFilterType type, uint32_t bufferSize,
+ const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) override;
+
+ virtual Return<void> getFilterQueueDesc(uint32_t filterId,
+ getFilterQueueDesc_cb _hidl_cb) override;
+
+ virtual Return<Result> configureFilter(uint32_t filterId,
+ const DemuxFilterSettings& settings) override;
+
+ virtual Return<Result> startFilter(uint32_t filterId) override;
+
+ virtual Return<Result> stopFilter(uint32_t filterId) override;
+
+ virtual Return<Result> flushFilter(uint32_t filterId) override;
+
+ virtual Return<Result> removeFilter(uint32_t filterId) override;
+
+ virtual Return<void> getAvSyncHwId(uint32_t filterId, getAvSyncHwId_cb _hidl_cb) override;
+
+ virtual Return<void> getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override;
+
+ private:
+ virtual ~Demux();
+ /**
+ * To create a FilterMQ with the the next available Filter ID.
+ * Creating Event Flag at the same time.
+ * Add the successfully created/saved FilterMQ into the local list.
+ *
+ * Return false is any of the above processes fails.
+ */
+ bool createAndSaveMQ(uint32_t bufferSize, uint32_t filterId);
+ void deleteEventFlag();
+ bool writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId);
+ Result startSectionFilterHandler(DemuxFilterEvent event);
+ Result startPesFilterHandler(DemuxFilterEvent& event);
+ Result startTsFilterHandler();
+ Result startMediaFilterHandler(DemuxFilterEvent& event);
+ Result startRecordFilterHandler(DemuxFilterEvent& event);
+ Result startPcrFilterHandler();
+ bool writeSectionsAndCreateEvent(DemuxFilterEvent& event, uint32_t sectionNum);
+ void filterThreadLoop(DemuxFilterEvent* event);
+ static void* __threadLoop(void* data);
+
+ uint32_t mDemuxId;
+ uint32_t mSourceFrontendId;
+ /**
+ * Record the last used filer id. Initial value is -1.
+ * Filter Id starts with 0.
+ */
+ uint32_t mLastUsedFilterId = -1;
+ /**
+ * A list of created FilterMQ ptrs.
+ * The array number is the filter ID.
+ */
+ vector<unique_ptr<FilterMQ>> mFilterMQs;
+ vector<DemuxFilterType> mFilterTypes;
+ vector<EventFlag*> mFilterEventFlags;
+ /**
+ * Demux callbacks used on filter events or IO buffer status
+ */
+ vector<sp<IDemuxCallback>> mDemuxCallbacks;
+ /**
+ * How many times a specific filter has written since started
+ */
+ vector<uint16_t> mFilterWriteCount;
+ pthread_t mThreadId = 0;
+ /**
+ * If a specific filter's writing loop is still running
+ */
+ vector<bool> mThreadRunning;
+ /**
+ * Lock to protect writes to the FMQs
+ */
+ std::mutex mWriteLock;
+ /**
+ * How many times a filter should write
+ * TODO make this dynamic/random/can take as a parameter
+ */
+ const uint16_t SECTION_WRITE_COUNT = 10;
+ // A struct that passes the arguments to a newly created filter thread
+ struct ThreadArgs {
+ Demux* user;
+ DemuxFilterEvent* event;
+ };
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
diff --git a/tv/tuner/1.0/default/Descrambler.cpp b/tv/tuner/1.0/default/Descrambler.cpp
new file mode 100644
index 0000000..085f2c8
--- /dev/null
+++ b/tv/tuner/1.0/default/Descrambler.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.0-Descrambler"
+
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+#include "Descrambler.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Descrambler::Descrambler() {}
+
+Descrambler::~Descrambler() {}
+
+Return<Result> Descrambler::setDemuxSource(uint32_t demuxId) {
+ ALOGV("%s", __FUNCTION__);
+ if (mDemuxSet) {
+ ALOGW("[ WARN ] Descrambler has already been set with a demux id %d", mSourceDemuxId);
+ return Result::INVALID_STATE;
+ }
+ mDemuxSet = true;
+ mSourceDemuxId = demuxId;
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::setKeyToken(const hidl_vec<uint8_t>& /* keyToken */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::addPid(uint16_t /* pid */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::removePid(uint16_t /* pid */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::close() {
+ ALOGV("%s", __FUNCTION__);
+ mDemuxSet = false;
+
+ return Result::SUCCESS;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/tuner/1.0/default/Descrambler.h b/tv/tuner/1.0/default/Descrambler.h
new file mode 100644
index 0000000..436adcf
--- /dev/null
+++ b/tv/tuner/1.0/default/Descrambler.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_DESCRAMBLER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_DESCRAMBLER_H_
+
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::IDescrambler;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+class Descrambler : public IDescrambler {
+ public:
+ Descrambler();
+
+ virtual Return<Result> setDemuxSource(uint32_t demuxId) override;
+
+ virtual Return<Result> setKeyToken(const hidl_vec<uint8_t>& keyToken) override;
+
+ virtual Return<Result> addPid(uint16_t pid) override;
+
+ virtual Return<Result> removePid(uint16_t pid) override;
+
+ virtual Return<Result> close() override;
+
+ private:
+ virtual ~Descrambler();
+ uint32_t mSourceDemuxId;
+ bool mDemuxSet = false;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_TV_TUNER_V1_DESCRAMBLER_H_
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
new file mode 100644
index 0000000..3dcc2b1
--- /dev/null
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.0-Frontend"
+
+#include "Frontend.h"
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Frontend::Frontend() {
+ // Init callback to nullptr
+ mCallback = nullptr;
+}
+
+Frontend::Frontend(FrontendType type, FrontendId id) {
+ mType = type;
+ mId = id;
+ // Init callback to nullptr
+ mCallback = nullptr;
+}
+
+Frontend::~Frontend() {}
+
+Return<Result> Frontend::close() {
+ ALOGV("%s", __FUNCTION__);
+ // Reset callback
+ mCallback = nullptr;
+
+ return Result::SUCCESS;
+}
+
+Return<Result> Frontend::setCallback(const sp<IFrontendCallback>& callback) {
+ ALOGV("%s", __FUNCTION__);
+ if (callback == nullptr) {
+ ALOGW("[ WARN ] Set Frontend callback with nullptr");
+ return Result::INVALID_ARGUMENT;
+ }
+
+ mCallback = callback;
+ return Result::SUCCESS;
+}
+
+Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
+ ALOGV("%s", __FUNCTION__);
+ if (mCallback == nullptr) {
+ ALOGW("[ WARN ] Frontend callback is not set when tune");
+ return Result::INVALID_STATE;
+ }
+
+ mCallback->onEvent(FrontendEventType::NO_SIGNAL);
+ return Result::SUCCESS;
+}
+
+Return<Result> Frontend::stopTune() {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
+FrontendType Frontend::getFrontendType() {
+ return mType;
+}
+
+FrontendId Frontend::getFrontendId() {
+ return mId;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
new file mode 100644
index 0000000..f77a0d8
--- /dev/null
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
+
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendType;
+using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+class Frontend : public IFrontend {
+ public:
+ Frontend();
+ Frontend(FrontendType type, FrontendId id);
+
+ virtual Return<Result> close() override;
+
+ virtual Return<Result> setCallback(const sp<IFrontendCallback>& callback) override;
+
+ virtual Return<Result> tune(const FrontendSettings& settings) override;
+
+ virtual Return<Result> stopTune() override;
+
+ FrontendType getFrontendType();
+
+ FrontendId getFrontendId();
+
+ private:
+ virtual ~Frontend();
+ sp<IFrontendCallback> mCallback;
+ FrontendType mType = FrontendType::UNDEFINED;
+ FrontendId mId = 0;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
diff --git a/tv/tuner/1.0/default/OWNERS b/tv/tuner/1.0/default/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.0/default/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
new file mode 100644
index 0000000..68b3436
--- /dev/null
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.0-Tuner"
+
+#include "Tuner.h"
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+#include "Demux.h"
+#include "Descrambler.h"
+#include "Frontend.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::DemuxId;
+
+Tuner::Tuner() {
+ // Static Frontends array to maintain local frontends information
+ // Array index matches their FrontendId in the default impl
+ mFrontendSize = 8;
+ mFrontends.resize(mFrontendSize);
+ mFrontends[0] = new Frontend();
+ mFrontends[1] = new Frontend(FrontendType::ATSC, 1);
+ mFrontends[2] = new Frontend(FrontendType::DVBC, 2);
+ mFrontends[3] = new Frontend(FrontendType::DVBS, 3);
+ mFrontends[4] = new Frontend(FrontendType::DVBT, 4);
+ mFrontends[5] = new Frontend(FrontendType::ISDBT, 5);
+ mFrontends[6] = new Frontend(FrontendType::ANALOG, 6);
+ mFrontends[7] = new Frontend(FrontendType::ATSC, 7);
+}
+
+Tuner::~Tuner() {}
+
+Return<void> Tuner::getFrontendIds(getFrontendIds_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ vector<FrontendId> frontendIds;
+ frontendIds.resize(mFrontendSize);
+ for (int i = 0; i < mFrontendSize; i++) {
+ frontendIds[i] = mFrontends[i]->getFrontendId();
+ }
+
+ _hidl_cb(Result::SUCCESS, frontendIds);
+ return Void();
+}
+
+Return<void> Tuner::openFrontendById(uint32_t frontendId, openFrontendById_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ if (frontendId >= mFrontendSize || frontendId < 0) {
+ ALOGW("[ WARN ] Frontend with id %d isn't available", frontendId);
+ _hidl_cb(Result::UNAVAILABLE, nullptr);
+ return Void();
+ }
+
+ _hidl_cb(Result::SUCCESS, mFrontends[frontendId]);
+ return Void();
+}
+
+Return<void> Tuner::openDemux(openDemux_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ DemuxId demuxId = mLastUsedId + 1;
+ mLastUsedId += 1;
+ sp<IDemux> demux = new Demux(demuxId);
+
+ _hidl_cb(Result::SUCCESS, demuxId, demux);
+ return Void();
+}
+
+Return<void> Tuner::openDescrambler(openDescrambler_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ sp<IDescrambler> descrambler = new Descrambler();
+
+ _hidl_cb(Result::SUCCESS, descrambler);
+ return Void();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
new file mode 100644
index 0000000..12e9594
--- /dev/null
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
+
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include "Frontend.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+class Tuner : public ITuner {
+ public:
+ Tuner();
+ virtual Return<void> getFrontendIds(getFrontendIds_cb _hidl_cb) override;
+
+ virtual Return<void> openFrontendById(uint32_t frontendId,
+ openFrontendById_cb _hidl_cb) override;
+
+ virtual Return<void> openDemux(openDemux_cb _hidl_cb) override;
+
+ virtual Return<void> openDescrambler(openDescrambler_cb _hidl_cb) override;
+
+ private:
+ virtual ~Tuner();
+ // Static mFrontends array to maintain local frontends information
+ vector<sp<Frontend>> mFrontends;
+ // To maintain how many Frontends we have
+ int mFrontendSize;
+ // The last used demux id. Initial value is -1.
+ // First used id will be 0.
+ int mLastUsedId = -1;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace tuner
+} // namespace tv
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
new file mode 100644
index 0000000..ad72fae
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
@@ -0,0 +1,9 @@
+service vendor.tuner-hal-1-0 /vendor/bin/hw/android.hardware.tv.tuner@1.0-service-lazy
+ interface android.hardware.tv.tuner@1.0::ITuner default
+ oneshot
+ disabled
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml
new file mode 100644
index 0000000..4bcfe10
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.tv.tuner</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ITuner</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
new file mode 100644
index 0000000..6d59ed7
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
@@ -0,0 +1,6 @@
+service vendor.tuner-hal-1-0 /vendor/bin/hw/android.hardware.tv.tuner@1.0-service
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml
new file mode 100644
index 0000000..4bcfe10
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+ <hal format="hidl">
+ <name>android.hardware.tv.tuner</name>
+ <transport>hwbinder</transport>
+ <version>1.0</version>
+ <interface>
+ <name>ITuner</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/service.cpp b/tv/tuner/1.0/default/service.cpp
new file mode 100644
index 0000000..581d269
--- /dev/null
+++ b/tv/tuner/1.0/default/service.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#ifdef LAZY_SERVICE
+#define LOG_TAG "android.hardware.tv.tuner@1.0-service-lazy"
+#else
+#define LOG_TAG "android.hardware.tv.tuner@1.0-service"
+#endif
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "Tuner.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::implementation::Tuner;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main() {
+ configureRpcThreadpool(8, true /* callerWillJoin */);
+
+ // Setup hwbinder service
+ android::sp<ITuner> service = new Tuner();
+ android::status_t status;
+ if (kLazyService) {
+ auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
+ status = serviceRegistrar->registerService(service);
+ } else {
+ status = service->registerAsService();
+ }
+ LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering tuner service: %d", status);
+
+ joinRpcThreadpool();
+ return 0;
+}
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
new file mode 100644
index 0000000..4522db2
--- /dev/null
+++ b/tv/tuner/1.0/types.hal
@@ -0,0 +1,481 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.0;
+
+import android.hidl.safe_union@1.0;
+
+@export
+enum Result : int32_t {
+ SUCCESS,
+ UNAVAILABLE,
+ NOT_INITIALIZED,
+ INVALID_STATE,
+ INVALID_ARGUMENT,
+ OUT_OF_MEMORY,
+ UNKNOWN_ERROR,
+};
+
+/**
+ * Frontend ID.
+ */
+typedef uint32_t FrontendId;
+
+/**
+ * Frontend Types.
+ */
+@export
+enum FrontendType : uint32_t {
+ UNDEFINED = 0,
+ ANALOG,
+ ATSC,
+ DVBC,
+ DVBS,
+ DVBT,
+ ISDBT,
+};
+
+/**
+ * Inner Forward Error Correction type as specified in ETSI EN 300 468 V1.15.1
+ * It's a 4-bit field specifying the inner FEC scheme used according to the
+ * table 35 in the spec.
+ */
+@export
+enum FrontendInnerFec : uint32_t {
+ /* Not defined */
+ FEC_UNDEFINED = 0,
+ /* 1/2 conv. code rate */
+ FEC_1_2 = 1 << 0,
+ /* 2/3 conv. code rate */
+ FEC_2_3 = 1 << 1,
+ /* 3/4 conv. code rate */
+ FEC_3_4 = 1 << 2,
+ /* 5/6 conv. code rate */
+ FEC_5_6 = 1 << 3,
+ /* 7/8 conv. code rate */
+ FEC_7_8 = 1 << 4,
+ /* 8/9 conv. code rate */
+ FEC_8_9 = 1 << 5,
+ /* 3/5 conv. code rate */
+ FEC_3_5 = 1 << 6,
+ /* 4/5 conv. code rate */
+ FEC_4_5 = 1 << 7,
+ /* 9/10 conv. code rate */
+ FEC_9_10 = 1 << 8,
+ /* hardware is able to detect and set FEC automatically */
+ FEC_AUTO = 1 << 9,
+};
+
+/**
+ * Modulation Type for ATSC.
+ */
+@export
+enum FrontendAtscModulation : uint32_t {
+ UNDEFINED = 0,
+ MOD_8VSB = 1 << 0,
+ MOD_16VSB = 1 << 1,
+};
+
+/**
+ * Signal Setting for ATSC Frontend.
+ */
+struct FrontendAtscSettings {
+ /** Signal frequencey in Herhz */
+ uint32_t frequency;
+ FrontendAtscModulation modulation;
+};
+
+/**
+ * Signal Setting for DVBT Frontend.
+ */
+struct FrontendDvbtSettings {
+ /** Signal frequencey in Herhz */
+ uint32_t frequency;
+ FrontendAtscModulation modulation;
+ FrontendInnerFec fec;
+};
+
+/**
+ * Modulation Type for ATSC.
+ */
+safe_union FrontendSettings {
+ FrontendAtscSettings atsc;
+ FrontendDvbtSettings dvbt;
+};
+
+/**
+ * Frontend Event Type.
+ */
+@export
+enum FrontendEventType : uint32_t {
+ /**
+ * If frontend locked the signal which is specified by tune method, HAL sent
+ * Locked event.
+ */
+ LOCKED,
+ /**
+ * If frontend can't locked the signal which is specified by tune method,
+ * HAL sent NO_SIGNAL event.
+ */
+ NO_SIGNAL,
+ /**
+ * If frontend detect that the locked signal get lost, HAL sent LOST_LOCK
+ * event.
+ */
+ LOST_LOCK,
+};
+
+/* Demux ID is used to associate with a hardware demux resource. */
+typedef uint32_t DemuxId;
+
+/* Filter ID is used to associate with a hardware filter resource. */
+typedef uint32_t DemuxFilterId;
+
+/**
+ * Filter Type according to ISO/IEC 13818-1
+ */
+@export
+enum DemuxFilterType : uint32_t {
+ /**
+ * A filter to filter section data out from input stream.
+ */
+ SECTION,
+ /**
+ * A filter to filter PES data out from input stream.
+ */
+ PES,
+ /**
+ * A filter to filter TS payload out from input stream.
+ */
+ TS,
+ /**
+ * A filter to filter Audio Metadata out from input stream.
+ */
+ AUDIO,
+ /**
+ * A filter to filter Vidoe Metadata out from input stream.
+ */
+ VIDEO,
+ /**
+ * A filter to set PCR (Program Clock Reference) channel from input stream.
+ */
+ PCR,
+ /**
+ * A filter to filter data directly to output buffer for record.
+ */
+ RECORD,
+};
+
+/* Packet ID is used to specify packets in transport stream. */
+typedef uint16_t DemuxTpid;
+
+@export
+enum Constant : uint16_t {
+ /**
+ * An invalid packet ID in transport stream according to ISO/IEC 13818-1.
+ */
+ INVALID_TPID = 0xFFFF,
+ /**
+ * An invalid Stream ID.
+ */
+ INVALID_STREAM_ID = 0xFFFF,
+};
+
+/**
+ * A status of data in the filter's buffer.
+ */
+@export
+enum DemuxFilterStatus : uint8_t {
+ /**
+ * The data in the filter buffer is ready to be read.
+ */
+ DATA_READY = 1 << 0,
+ /**
+ * The available data amount in the filter buffer is at low level which is
+ * set to 25 percent by default.
+ */
+ LOW_WATER = 1 << 1,
+ /**
+ * The available data amount in the filter buffer is at high level which is
+ * set to 75 percent by default.
+ */
+ HIGH_WATER = 1 << 2,
+ /**
+ * The data in the filter buffer is full and newly filtered data is being
+ * discarded.
+ */
+ OVERFLOW = 1 << 3,
+};
+
+/**
+ * Bits Setting for Section Filter.
+ */
+struct DemuxFilterSectionBits {
+ /* The bytes are configured for Section Filter */
+ vec<uint8_t> filter;
+ /* Active bits in the configured bytes to be used for filtering */
+ vec<uint8_t> mask;
+ /*
+ * Do positive match at the bit position of the configured bytes when the
+ * bit at same position of the mode is 0.
+ * Do negative match at the bit position of the configured bytes when the
+ * bit at same position of the mode is 1.
+ */
+ vec<uint8_t> mode;
+};
+
+/**
+ * Filter Settings for Section data according to ISO/IEC 13818-1.
+ */
+struct DemuxFilterSectionSettings {
+ DemuxTpid tpid;
+ DemuxFilterSectionBits bits;
+ /* Table ID for Section Filter */
+ uint16_t tableId;
+ /* Version number for Section Filter */
+ uint16_t version;
+ /* true if the filter checks CRC and discards data with wrong CRC */
+ bool checkCrc;
+ /* true if the filter repeats the data with the same version */
+ bool isRepeat;
+ /* true if the filter output raw data */
+ bool isRaw;
+};
+
+/* Stream ID is used to specify one elementary stream */
+typedef uint16_t DemuxStreamId;
+
+/**
+ * Filter Settings for a PES Data.
+ */
+struct DemuxFilterPesDataSettings {
+ DemuxTpid tpid;
+ DemuxStreamId streamId;
+ /* true if the filter output raw data */
+ bool bIsRaw;
+};
+
+/**
+ * Filter Settings for a TS Data.
+ */
+struct DemuxFilterTsSettings {
+ DemuxTpid tpid;
+};
+
+/**
+ * Filter Settings for a Audio.
+ */
+struct DemuxFilterAudioSettings {
+ DemuxTpid tpid;
+ /**
+ * true if the filter output goes to decoder directly in pass through mode.
+ */
+ bool bPassthrough;
+};
+
+/**
+ * Filter Settings for a Video.
+ */
+struct DemuxFilterVideoSettings {
+ DemuxTpid tpid;
+ /**
+ * true if the filter output goes to decoder directly in pass through mode.
+ */
+ bool bPassthrough;
+};
+
+/**
+ * Filter Settings for a PCR (Program Clock Reference).
+ */
+struct DemuxFilterPcrSettings {
+ DemuxTpid tpid;
+};
+
+/**
+ * Indexes can be tagged through TS (Transport Stream) header.
+ */
+@export
+enum DemuxTsIndex : uint32_t {
+ FIRST_PACKET = 1 << 0,
+ PAYLOAD_UNIT_START_INDICATOR = 1 << 1,
+ CHANGE_TO_NOT_SCRAMBLED = 1 << 2,
+ CHANGE_TO_EVEN_SCRAMBLED = 1 << 3,
+ CHANGE_TO_ODD_SCRAMBLED = 1 << 4,
+ DISCONTINUITY_INDICATOR = 1 << 5,
+ RANDOM_ACCESS_INDICATOR = 1 << 6,
+ PRIORITY_INDICATOR = 1 << 7,
+ PCR_FLAG = 1 << 8,
+ OPCR_FLAG = 1 << 9,
+ SPLICING_POINT_FLAG = 1 << 10,
+ PRIVATE_DATA = 1 << 11,
+ ADAPTATION_EXTENSION_FLAG = 1 << 12,
+};
+
+/**
+ * A mask of TS indexes
+ *
+ * It's a combination of TS indexes.
+ */
+typedef bitfield<DemuxTsIndex> DemuxTsIndexMask;
+
+/**
+ * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
+ * according to ISO/IEC 13818-1.
+ */
+@export
+enum DemuxScIndex : uint32_t {
+ /* Start Code is for a new I Frame */
+ I_FRAME = 1 << 0,
+ /* Start Code is for a new P Frame */
+ P_FRAME = 1 << 1,
+ /* Start Code is for a new B Frame */
+ B_FRAME = 1 << 2,
+ /* Start Code is for a new Sequence */
+ SEQUENCE = 1 << 3,
+};
+
+/**
+ * A mask of Start Code Indexes
+ *
+ * It's a combination of Start Code Indexes.
+ */
+typedef bitfield<DemuxScIndex> DemuxScIndexMask;
+
+/* Index type to be used in the filter for record */
+@export
+enum DemuxRecordIndexType : uint32_t {
+ /* Don't use index */
+ NONE,
+ /* Use TS index */
+ TS,
+ /* Use Start Code index */
+ SC,
+};
+
+/**
+ * Filter Settings for Record data.
+ */
+struct DemuxFilterRecordSettings {
+ DemuxTpid tpid;
+ DemuxRecordIndexType indexType;
+ safe_union IndexMask {
+ DemuxTsIndexMask tsIndexMask;
+ DemuxScIndexMask scIndexMask;
+ } indexMask;
+};
+
+/**
+ * Filter Settings.
+ */
+safe_union DemuxFilterSettings {
+ DemuxFilterSectionSettings section;
+ DemuxFilterPesDataSettings pesData;
+ DemuxFilterTsSettings ts;
+ DemuxFilterAudioSettings audio;
+ DemuxFilterVideoSettings video;
+ DemuxFilterPcrSettings pcr;
+ DemuxFilterRecordSettings record;
+};
+
+/**
+ * The bits of EventFlag in FMQ (Fast message queue) are used by client to
+ * notify HAL the status change.
+ */
+@export
+enum DemuxQueueNotifyBits : uint32_t {
+ /* client writes data and notify HAL the data is ready. */
+ DATA_READY = 1 << 0,
+ /* client reads data and notify HAL the data is consumed. */
+ DATA_CONSUMED = 1 << 1
+};
+
+/**
+ * Filter Event for Section Filter.
+ */
+struct DemuxFilterSectionEvent {
+ /* Table ID of filtered data */
+ uint16_t tableId;
+ /* Version number of filtered data */
+ uint16_t version;
+ /* Section number of filtered data */
+ uint16_t sectionNum;
+ /* Data size in bytes of filtered data */
+ uint16_t dataLength;
+};
+
+/**
+ * Filter Event for Audio or Video Filter.
+ */
+struct DemuxFilterMediaEvent {
+ /* Presentation Time Stamp for audio or video frame. It based on 90KHz has
+ * the same format as PTS (Presentation Time Stamp).
+ */
+ uint64_t pts;
+ /* Data size in bytes of audio or video frame */
+ uint16_t dataLength;
+ /* A handle associated to the memory where audio or video data stays. */
+ handle secureMemory;
+};
+
+/**
+ * Filter Event for PES data.
+ */
+struct DemuxFilterPesEvent {
+ DemuxStreamId streamId;
+ /* Data size in bytes of PES data */
+ uint16_t dataLength;
+};
+
+/**
+ * Filter Event for Record data.
+ */
+struct DemuxFilterRecordEvent {
+ DemuxTpid tpid;
+ /* Indexes of record output */
+ safe_union IndexMask {
+ DemuxTsIndexMask tsIndexMask;
+ DemuxScIndexMask scIndexMask;
+ } indexMask;
+ /* Packet number from beginning of the filter's output */
+ uint64_t packetNum;
+};
+
+/**
+ * Filter Event.
+ */
+struct DemuxFilterEvent {
+ DemuxFilterId filterId;
+ DemuxFilterType filterType;
+ safe_union Event {
+ DemuxFilterSectionEvent section;
+ DemuxFilterMediaEvent media;
+ DemuxFilterPesEvent pes;
+ DemuxFilterRecordEvent ts;
+ };
+ /* An array of events */
+ vec<Event> events;
+};
+
+/**
+ * A hardware resource ID to be used for audio and video hardware sync.
+ */
+typedef uint32_t AvSyncHwId;
+
+/**
+ * A token to be used to link descrambler and key slot. It's opaque to
+ * framework and apps.
+ */
+typedef vec<uint8_t> TunerKeyToken;
diff --git a/tv/tuner/1.0/vts/OWNERS b/tv/tuner/1.0/vts/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.0/vts/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..faf566c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+ name: "VtsHalTvTunerV1_0TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalTvTunerV1_0TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.tv.tuner@1.0",
+ "android.hidl.allocator@1.0",
+ "android.hidl.memory@1.0",
+ "libhidlallocatorutils",
+ "libhidlmemory",
+ ],
+ shared_libs: [
+ "libbinder",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
new file mode 100644
index 0000000..c652944
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Tuner_hidl_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/IDemuxCallback.h>
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+
+#define WAIT_TIMEOUT 3000000000
+
+using android::Condition;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+using android::hardware::fromHeap;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::HidlMemory;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendEventType;
+using android::hardware::tv::tuner::V1_0::FrontendId;
+using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IDemuxCallback;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+using android::hardware::tv::tuner::V1_0::IFrontend;
+using android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+namespace {
+
+class FrontendCallback : public IFrontendCallback {
+ public:
+ virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ mEventReceived = true;
+ mEventType = frontendEventType;
+ mMsgCondition.signal();
+ return Void();
+ }
+
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override {
+ android::Mutex::Autolock autoLock(mMsgLock);
+ mDiseqcMessageReceived = true;
+ mEventMessage = diseqcMessage;
+ mMsgCondition.signal();
+ return Void();
+ }
+
+ void testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings);
+ void testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings);
+
+ private:
+ bool mEventReceived = false;
+ bool mDiseqcMessageReceived = false;
+ FrontendEventType mEventType;
+ hidl_vec<uint8_t> mEventMessage;
+ android::Mutex mMsgLock;
+ android::Condition mMsgCondition;
+};
+
+void FrontendCallback::testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "event not received within timeout";
+ return;
+ }
+ }
+}
+
+void FrontendCallback::testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings) {
+ Result result = frontend->tune(settings);
+
+ EXPECT_TRUE(result == Result::SUCCESS);
+
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (!mDiseqcMessageReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "diseqc message not received within timeout";
+ return;
+ }
+ }
+}
+
+// Test environment for Tuner HIDL HAL.
+class TunerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static TunerHidlEnvironment* Instance() {
+ static TunerHidlEnvironment* instance = new TunerHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<ITuner>(); }
+};
+
+class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+ virtual void SetUp() override {
+ mService = ::testing::VtsHalHidlTargetTestBase::getService<ITuner>(
+ TunerHidlEnvironment::Instance()->getServiceName<ITuner>());
+ ASSERT_NE(mService, nullptr);
+ }
+
+ sp<ITuner> mService;
+
+ protected:
+ static void description(const std::string& description) {
+ RecordProperty("description", description);
+ }
+
+ sp<IFrontend> mFrontend;
+ sp<FrontendCallback> mFrontendCallback;
+ sp<IDescrambler> mDescrambler;
+ sp<IDemux> mDemux;
+ uint32_t mDemuxId;
+
+ ::testing::AssertionResult createFrontend(int32_t frontendId);
+ ::testing::AssertionResult tuneFrontend(int32_t frontendId);
+ ::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
+ ::testing::AssertionResult closeFrontend(int32_t frontendId);
+ ::testing::AssertionResult createDemux();
+ ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId);
+ ::testing::AssertionResult closeDemux();
+ ::testing::AssertionResult createDescrambler();
+ ::testing::AssertionResult closeDescrambler();
+};
+
+::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
+ Result status;
+
+ mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
+ mFrontend = frontend;
+ status = result;
+ });
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ mFrontendCallback = new FrontendCallback();
+ auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+
+ return ::testing::AssertionResult(callbackStatus.isOk());
+}
+
+::testing::AssertionResult TunerHidlTest::tuneFrontend(int32_t frontendId) {
+ if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Frontend Settings for testing
+ FrontendSettings frontendSettings;
+ FrontendAtscSettings frontendAtscSettings{
+ .frequency = 0,
+ .modulation = FrontendAtscModulation::UNDEFINED,
+ };
+ frontendSettings.atsc() = frontendAtscSettings;
+ mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
+
+ FrontendDvbtSettings frontendDvbtSettings{
+ .frequency = 0,
+ .modulation = FrontendAtscModulation::UNDEFINED,
+ .fec = FrontendInnerFec::FEC_UNDEFINED,
+ };
+ frontendSettings.dvbt(frontendDvbtSettings);
+ mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
+
+ return ::testing::AssertionResult(true);
+}
+
+::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) {
+ Result status;
+ if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mFrontend->stopTune();
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) {
+ Result status;
+ if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mFrontend->close();
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDemux() {
+ Result status;
+
+ mService->openDemux([&](Result result, uint32_t demuxId, const sp<IDemux>& demux) {
+ mDemux = demux;
+ mDemuxId = demuxId;
+ status = result;
+ });
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId) {
+ Result status;
+
+ if (createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mDemux->setFrontendDataSource(frontendId);
+
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::closeDemux() {
+ Result status;
+ if (createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mDemux->close();
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDescrambler() {
+ Result status;
+
+ mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
+ mDescrambler = descrambler;
+ status = result;
+ });
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ if (createDemux() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mDescrambler->setDemuxSource(mDemuxId);
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+
+ // Test if demux source can be set more than once.
+ status = mDescrambler->setDemuxSource(mDemuxId);
+ return ::testing::AssertionResult(status == Result::INVALID_STATE);
+}
+
+::testing::AssertionResult TunerHidlTest::closeDescrambler() {
+ Result status;
+ if (createDescrambler() == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+
+ status = mDescrambler->close();
+ return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+TEST_F(TunerHidlTest, CreateFrontend) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ description("Create Frontends");
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return;
+ }
+
+ for (size_t i = 0; i < feIds.size(); i++) {
+ ASSERT_TRUE(createFrontend(feIds[i]));
+ }
+}
+
+TEST_F(TunerHidlTest, TuneFrontend) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ description("Tune Frontends and check callback onEvent");
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return;
+ }
+
+ for (size_t i = 0; i < feIds.size(); i++) {
+ ASSERT_TRUE(tuneFrontend(feIds[i]));
+ }
+}
+
+TEST_F(TunerHidlTest, StopTuneFrontend) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ description("stopTune Frontends");
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return;
+ }
+
+ for (size_t i = 0; i < feIds.size(); i++) {
+ ASSERT_TRUE(stopTuneFrontend(feIds[i]));
+ }
+}
+
+TEST_F(TunerHidlTest, CloseFrontend) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ description("Close Frontends");
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return;
+ }
+
+ for (size_t i = 0; i < feIds.size(); i++) {
+ ASSERT_TRUE(closeFrontend(feIds[i]));
+ }
+}
+
+TEST_F(TunerHidlTest, CreateDemux) {
+ description("Create Demux");
+
+ ASSERT_TRUE(createDemux());
+}
+
+TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ description("Create Demux with Frontend");
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return;
+ }
+
+ for (size_t i = 0; i < feIds.size(); i++) {
+ ASSERT_TRUE(createDemuxWithFrontend(feIds[i]));
+ }
+}
+
+TEST_F(TunerHidlTest, CloseDemux) {
+ description("Close Demux");
+
+ ASSERT_TRUE(closeDemux());
+}
+
+TEST_F(TunerHidlTest, CreateDescrambler) {
+ description("Create Descrambler");
+
+ ASSERT_TRUE(createDescrambler());
+}
+
+TEST_F(TunerHidlTest, CloseDescrambler) {
+ description("Close Descrambler");
+
+ ASSERT_TRUE(closeDescrambler());
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ::testing::AddGlobalTestEnvironment(TunerHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ TunerHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ LOG(INFO) << "Test result = " << status;
+ return status;
+}
diff --git a/usb/1.0/default/Android.bp b/usb/1.0/default/Android.bp
index 64de821..96d24c1 100644
--- a/usb/1.0/default/Android.bp
+++ b/usb/1.0/default/Android.bp
@@ -26,7 +26,6 @@
shared_libs: [
"libcutils",
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"libhardware",
diff --git a/vibrator/1.0/default/Android.bp b/vibrator/1.0/default/Android.bp
index 0c7d155..b0d0986 100644
--- a/vibrator/1.0/default/Android.bp
+++ b/vibrator/1.0/default/Android.bp
@@ -21,7 +21,6 @@
srcs: ["Vibrator.cpp"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"libhardware",
@@ -39,7 +38,6 @@
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"libhardware",
diff --git a/vibrator/1.3/example/Android.bp b/vibrator/1.3/example/Android.bp
index 36f2ff8..07f1c26 100644
--- a/vibrator/1.3/example/Android.bp
+++ b/vibrator/1.3/example/Android.bp
@@ -23,7 +23,6 @@
cflags: ["-Wall", "-Werror"],
shared_libs: [
"libhidlbase",
- "libhidltransport",
"liblog",
"libutils",
"android.hardware.vibrator@1.0",
diff --git a/vr/1.0/default/Android.bp b/vr/1.0/default/Android.bp
index ddc1bfb..cfb2808 100644
--- a/vr/1.0/default/Android.bp
+++ b/vr/1.0/default/Android.bp
@@ -12,7 +12,6 @@
"libcutils",
"libutils",
"libhidlbase",
- "libhidltransport",
"android.hardware.vr@1.0",
],
}
@@ -30,7 +29,6 @@
"libutils",
"libhardware",
"libhidlbase",
- "libhidltransport",
"android.hardware.vr@1.0",
],
}
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 0a3809c..29f1c42 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -59,7 +59,6 @@
libbase \
libcutils \
libhidlbase \
- libhidltransport \
liblog \
libnl \
libutils \
@@ -86,7 +85,6 @@
libbase \
libcutils \
libhidlbase \
- libhidltransport \
liblog \
libnl \
libutils \
@@ -117,7 +115,6 @@
libbase \
libcutils \
libhidlbase \
- libhidltransport \
liblog \
libnl \
libutils \
@@ -160,7 +157,6 @@
libbase \
libcutils \
libhidlbase \
- libhidltransport \
liblog \
libnl \
libutils \