Merge "Add VtsHalLightV2_0TargetTest and VtsHalNeuralnetworksV1_* to vts-core"
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index bec22df..1a9df21 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -378,7 +378,7 @@
}
Return<Result> Device::setConnectedState(const DeviceAddress& address, bool connected) {
- auto key = connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect;
+ auto key = connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect;
return setParam(key, address);
}
#endif
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index b995657..e62f6d3 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -243,8 +243,8 @@
Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
return setParam(
- connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
- address);
+ connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
+ address);
}
#elif MAJOR_VERSION >= 4
Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index a46de24..fc441ed 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -671,7 +671,7 @@
.initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}}},
{.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
- .access = VehiclePropertyAccess::WRITE,
+ .access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE},
.initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f6ebcdd..0f20dd1 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1282,7 +1282,7 @@
*
* @change_mode VehiclePropertyChangeMode:ON_CHANGE
- * @access VehiclePropertyAccess:WRITE
+ * @access VehiclePropertyAccess:READ_WRITE
*/
AP_POWER_STATE_REPORT = (
0x0A01
diff --git a/boot/1.1/Android.bp b/boot/1.1/Android.bp
new file mode 100644
index 0000000..6a8d57a
--- /dev/null
+++ b/boot/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.boot@1.1",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IBootControl.hal",
+ ],
+ interfaces: [
+ "android.hardware.boot@1.0",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/boot/1.1/IBootControl.hal b/boot/1.1/IBootControl.hal
new file mode 100644
index 0000000..939dfb3
--- /dev/null
+++ b/boot/1.1/IBootControl.hal
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package android.hardware.boot@1.1;
+
+import @1.0::IBootControl;
+
+interface IBootControl extends @1.0::IBootControl {
+ /**
+ * Sets whether a snapshot-merge of any dynamic partition is in progress.
+ *
+ * After the merge status is set to a given value, subsequent calls to
+ * getSnapshotMergeStatus must return the set value.
+ *
+ * The merge status must be persistent across reboots. That is, getSnapshotMergeStatus
+ * must return the same value after a reboot if the merge status is not altered in any way
+ * (e.g. set by setSnapshotMergeStatus or set to CANCELLED by bootloader).
+ *
+ * Read/write access to the merge status must be atomic. When the HAL is processing a
+ * setSnapshotMergeStatus call, all subsequent calls to getSnapshotMergeStatus must block until
+ * setSnapshotMergeStatus has returned.
+ *
+ * A MERGING state indicates that dynamic partitions are partially comprised by blocks in the
+ * userdata partition.
+ *
+ * When the merge status is set to MERGING, the following operations must be prohibited from the
+ * bootloader:
+ * - Flashing or erasing "userdata" or "metadata".
+ *
+ * The following operations may be prohibited when the status is set to MERGING. If not
+ * prohibited, it is recommended that the user receive a warning.
+ * - Changing the active slot (e.g. via "fastboot set_active")
+ *
+ * @param status Merge status.
+ *
+ * @return success True on success, false otherwise.
+ */
+ setSnapshotMergeStatus(MergeStatus status) generates (bool success);
+
+ /**
+ * Returns whether a snapshot-merge of any dynamic partition is in progress.
+ *
+ * This function must return the merge status set by the last setSnapshotMergeStatus call and
+ * recorded by the bootloader with one exception. If the partitions are being flashed from the
+ * bootloader such that the pending merge must be canceled (for example, if the super partition
+ * is being flashed), this function must return CANCELLED.
+ *
+ * @return success True if the merge status is read successfully, false otherwise.
+ * @return status Merge status.
+ */
+ getSnapshotMergeStatus() generates (MergeStatus status);
+};
+
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
new file mode 100644
index 0000000..dca5c26
--- /dev/null
+++ b/boot/1.1/default/Android.bp
@@ -0,0 +1,43 @@
+cc_library_shared {
+ name: "android.hardware.boot@1.1-impl",
+ defaults: [
+ "hidl_defaults",
+ "libboot_control_defaults",
+ ],
+ relative_install_path: "hw",
+ vendor: true,
+ recovery_available: true,
+ srcs: ["BootControl.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libhidlbase",
+ "libhardware",
+ "libutils",
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ ],
+ static_libs: [
+ "libboot_control",
+ "libfstab",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.boot@1.1-service",
+ defaults: ["hidl_defaults"],
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["android.hardware.boot@1.1-service.rc"],
+ srcs: ["service.cpp"],
+
+ shared_libs: [
+ "liblog",
+ "libhardware",
+ "libhidlbase",
+ "libutils",
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ ],
+
+}
diff --git a/boot/1.1/default/BootControl.cpp b/boot/1.1/default/BootControl.cpp
new file mode 100644
index 0000000..c9c62a4
--- /dev/null
+++ b/boot/1.1/default/BootControl.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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.boot@1.1-impl"
+
+#include <memory>
+
+#include <log/log.h>
+
+#include "BootControl.h"
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::boot::V1_0::CommandResult;
+
+bool BootControl::Init() {
+ return impl_.Init();
+}
+
+// Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+Return<uint32_t> BootControl::getNumberSlots() {
+ return impl_.GetNumberSlots();
+}
+
+Return<uint32_t> BootControl::getCurrentSlot() {
+ return impl_.GetCurrentSlot();
+}
+
+Return<void> BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.MarkBootSuccessful()) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<void> BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.SetActiveBootSlot(slot)) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<void> BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) {
+ struct CommandResult cr;
+ if (impl_.SetSlotAsUnbootable(slot)) {
+ cr.success = true;
+ cr.errMsg = "Success";
+ } else {
+ cr.success = false;
+ cr.errMsg = "Operation failed";
+ }
+ _hidl_cb(cr);
+ return Void();
+}
+
+Return<BoolResult> BootControl::isSlotBootable(uint32_t slot) {
+ if (!impl_.IsValidSlot(slot)) {
+ return BoolResult::INVALID_SLOT;
+ }
+ return impl_.IsSlotBootable(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<BoolResult> BootControl::isSlotMarkedSuccessful(uint32_t slot) {
+ if (!impl_.IsValidSlot(slot)) {
+ return BoolResult::INVALID_SLOT;
+ }
+ return impl_.IsSlotMarkedSuccessful(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<void> BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) {
+ hidl_string ans;
+ const char* suffix = impl_.GetSuffix(slot);
+ if (suffix) {
+ ans = suffix;
+ }
+ _hidl_cb(ans);
+ return Void();
+}
+
+Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus status) {
+ return impl_.SetSnapshotMergeStatus(status);
+}
+
+Return<MergeStatus> BootControl::getSnapshotMergeStatus() {
+ return impl_.GetSnapshotMergeStatus();
+}
+
+IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
+ auto module = std::make_unique<BootControl>();
+ if (!module->Init()) {
+ ALOGE("Could not initialize BootControl module");
+ return nullptr;
+ }
+ return module.release();
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace boot
+} // namespace hardware
+} // namespace android
diff --git a/boot/1.1/default/BootControl.h b/boot/1.1/default/BootControl.h
new file mode 100644
index 0000000..75511b6
--- /dev/null
+++ b/boot/1.1/default/BootControl.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <libboot_control/libboot_control.h>
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_0::BoolResult;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+class BootControl : public IBootControl {
+ public:
+ bool Init();
+
+ // Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+ Return<uint32_t> getNumberSlots() override;
+ Return<uint32_t> getCurrentSlot() override;
+ Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
+ Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
+ Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
+ Return<BoolResult> isSlotBootable(uint32_t slot) override;
+ Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
+ Return<void> getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override;
+
+ // Methods from ::android::hardware::boot::V1_1::IBootControl follow.
+ Return<bool> setSnapshotMergeStatus(MergeStatus status) override;
+ Return<MergeStatus> getSnapshotMergeStatus() override;
+
+ private:
+ android::bootable::BootControl impl_;
+};
+
+extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name);
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace boot
+} // namespace hardware
+} // namespace android
diff --git a/boot/1.1/default/android.hardware.boot@1.1-service.rc b/boot/1.1/default/android.hardware.boot@1.1-service.rc
new file mode 100644
index 0000000..83fa9d0
--- /dev/null
+++ b/boot/1.1/default/android.hardware.boot@1.1-service.rc
@@ -0,0 +1,6 @@
+service vendor.boot-hal-1-1 /vendor/bin/hw/android.hardware.boot@1.1-service
+ interface android.hardware.boot@1.0::IBootControl default
+ interface android.hardware.boot@1.1::IBootControl default
+ class early_hal
+ user root
+ group root
diff --git a/boot/1.1/default/service.cpp b/boot/1.1/default/service.cpp
new file mode 100644
index 0000000..b24b464
--- /dev/null
+++ b/boot/1.1/default/service.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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.boot@1.1-service"
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::defaultPassthroughServiceImplementation;
+using ::android::hardware::boot::V1_1::IBootControl;
+
+int main(int /* argc */, char* /* argv */[]) {
+ return defaultPassthroughServiceImplementation<IBootControl>();
+}
diff --git a/boot/1.1/types.hal b/boot/1.1/types.hal
new file mode 100644
index 0000000..6346078
--- /dev/null
+++ b/boot/1.1/types.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.boot@1.1;
+
+enum MergeStatus : int32_t {
+ /**
+ * No snapshot or merge is in progress.
+ */
+ NONE = 0,
+
+ /**
+ * The merge status could not be determined.
+ */
+ UNKNOWN,
+
+ /**
+ * Partitions are being snapshotted, but no merge has been started.
+ */
+ SNAPSHOTTED,
+
+ /**
+ * At least one partition has merge is in progress.
+ */
+ MERGING,
+
+ /**
+ * A merge was in progress, but it was canceled by the bootloader.
+ */
+ CANCELLED,
+};
diff --git a/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..49ea09a
--- /dev/null
+++ b/boot/1.1/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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: "VtsHalBootV1_1TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalBootV1_1TargetTest.cpp"],
+ static_libs: [
+ "android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
+ "libgmock",
+ ],
+ test_suites: ["device-tests"],
+}
+
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
new file mode 100644
index 0000000..fba9a5e
--- /dev/null
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "boot_hidl_hal_test"
+
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <android/hardware/boot/1.1/types.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+using ::testing::Contains;
+
+class BootHidlTest : public testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ boot = IBootControl::getService(GetParam());
+ ASSERT_NE(boot, nullptr);
+
+ LOG(INFO) << "Test is remote " << boot->isRemote();
+ }
+
+ sp<IBootControl> boot;
+};
+
+static std::vector<MergeStatus> ValidMergeStatusValues() {
+ std::vector<MergeStatus> values;
+ for (const auto value : hidl_enum_range<MergeStatus>()) {
+ if (value == MergeStatus::UNKNOWN) {
+ continue;
+ }
+ values.push_back(value);
+ }
+ return values;
+}
+
+/**
+ * Ensure merge status can be retrieved.
+ */
+TEST_P(BootHidlTest, GetSnapshotMergeStatus) {
+ auto values = ValidMergeStatusValues();
+ auto status = (MergeStatus)boot->getSnapshotMergeStatus();
+ EXPECT_THAT(values, Contains(status));
+}
+
+/**
+ * Ensure merge status can be set to arbitrary value.
+ */
+TEST_P(BootHidlTest, SetSnapshotMergeStatus) {
+ for (const auto value : ValidMergeStatusValues()) {
+ EXPECT_TRUE(boot->setSnapshotMergeStatus(value).withDefault(false));
+ auto status = boot->getSnapshotMergeStatus();
+ EXPECT_EQ(status, value);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ , BootHidlTest,
+ testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
+ android::hardware::PrintInstanceNameToString);
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index be8d7ca..6a89dab 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -89,7 +89,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.boot</name>
- <version>1.0</version>
+ <version>1.1</version>
<interface>
<name>IBootControl</name>
<instance>default</instance>
@@ -467,7 +467,7 @@
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.vibrator</name>
- <version>1.0-3</version>
+ <version>1.0-4</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
diff --git a/contexthub/1.0/default/OWNERS b/contexthub/1.0/default/OWNERS
index 5373073..90c2330 100644
--- a/contexthub/1.0/default/OWNERS
+++ b/contexthub/1.0/default/OWNERS
@@ -1,4 +1,3 @@
-aarossig@google.com
arthuri@google.com
bduddie@google.com
-bstack@google.com
+stange@google.com
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index ee01441..045cc4e 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -1,8 +1,7 @@
#Context Hub team
-aarossig@google.com
arthuri@google.com
bduddie@google.com
-bstack@google.com
+stange@google.com
#VTS team
yim@google.com
diff --git a/current.txt b/current.txt
index 3fabd7c..972fe16 100644
--- a/current.txt
+++ b/current.txt
@@ -574,7 +574,15 @@
# ABI preserving changes to HALs during Android R
b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 android.hardware.neuralnetworks@1.0::IPreparedModel
+f1109cbb10297b7429a11fab42afa912710b303c9bf20bd5cdb8bd57b9c84186 android.hardware.neuralnetworks@1.0::types
+9d8ee57c490ffeaa28f702eaea8d198cb510e4bbfb99e6cb5f63e73341057c7c android.hardware.neuralnetworks@1.1::types
fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
+71c0f7127335e5b74d1615d5e7f129831b43ffbae5318ad0924d7d8d8910a859 android.hardware.neuralnetworks@1.2::types
+a785a57447a81e9c130eef6904c3a5c256076c6a04588c40620ebd6fa2660d77 android.hardware.radio@1.2::types
1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
+
+# HALs released in Android R
+07d0a252b2d8fa35887908a996ba395cf392968395fc30afab791f46e0c22a52 android.hardware.boot@1.1::IBootControl
+74049a402be913963edfdd80828a53736570e9d8124a1bf18166b6ed46a6b0ab android.hardware.boot@1.1::types
diff --git a/dumpstate/1.0/default/DumpstateDevice.cpp b/dumpstate/1.0/default/DumpstateDevice.cpp
index 25d92b0..c57bf43 100644
--- a/dumpstate/1.0/default/DumpstateDevice.cpp
+++ b/dumpstate/1.0/default/DumpstateDevice.cpp
@@ -37,11 +37,6 @@
// NOTE: this is just an example on how to use the DumpstateUtil.h functions to implement
// this interface.
- // Exit when dump is completed since this is a lazy HAL.
- addPostCommandTask([]() {
- exit(0);
- });
-
if (handle == nullptr || handle->numFds < 1) {
ALOGE("no FDs\n");
return Void();
diff --git a/dumpstate/1.0/default/service.cpp b/dumpstate/1.0/default/service.cpp
index 4f276b7..76c72b5 100644
--- a/dumpstate/1.0/default/service.cpp
+++ b/dumpstate/1.0/default/service.cpp
@@ -15,22 +15,26 @@
*/
#define LOG_TAG "android.hardware.dumpstate@1.0-service"
+#include <hidl/HidlLazyUtils.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include "DumpstateDevice.h"
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
-using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
-using ::android::hardware::joinRpcThreadpool;
using ::android::OK;
using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::LazyServiceRegistrar;
+using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
int main(int /* argc */, char* /* argv */ []) {
sp<IDumpstateDevice> dumpstate = new DumpstateDevice;
configureRpcThreadpool(1, true /* will join */);
- if (dumpstate->registerAsService() != OK) {
+
+ auto registrar = LazyServiceRegistrar::getInstance();
+ if (registrar.registerService(dumpstate) != OK) {
ALOGE("Could not register service.");
return 1;
}
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 9f7e1cd..a8e70ae 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -26,7 +26,6 @@
shared_libs: [
"libfmq",
"libhidlbase",
- "libhidltransport",
"libsync",
],
static_libs: [
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
index 5ad2a65..8134174 100644
--- a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
@@ -80,17 +80,21 @@
}
Return<Error> freeBuffer(void* buffer) override {
- native_handle_t* bufferHandle = removeImportedBuffer(buffer);
+ native_handle_t* bufferHandle = getImportedBuffer(buffer);
if (!bufferHandle) {
return Error::BAD_BUFFER;
}
- return mHal->freeBuffer(bufferHandle);
+ Error error = mHal->freeBuffer(bufferHandle);
+ if (error == Error::NONE) {
+ removeImportedBuffer(buffer);
+ }
+ return error;
}
Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
- const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
@@ -112,7 +116,7 @@
Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
const hidl_handle& acquireFence,
IMapper::lockYCbCr_cb hidl_cb) override {
- const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
return Void();
@@ -132,7 +136,7 @@
}
Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
- const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+ const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
if (!bufferHandle) {
hidl_cb(Error::BAD_BUFFER, nullptr);
return Void();
@@ -160,7 +164,11 @@
return static_cast<native_handle_t*>(buffer);
}
- virtual const native_handle_t* getImportedBuffer(void* buffer) const {
+ virtual native_handle_t* getImportedBuffer(void* buffer) const {
+ return static_cast<native_handle_t*>(buffer);
+ }
+
+ virtual const native_handle_t* getConstImportedBuffer(void* buffer) const {
return static_cast<const native_handle_t*>(buffer);
}
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
index e8b1b4b..85a91c3 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -68,7 +68,14 @@
return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
}
- const native_handle_t* get(void* buffer) {
+ native_handle_t* get(void* buffer) {
+ auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+ }
+
+ const native_handle_t* getConst(void* buffer) {
auto bufferHandle = static_cast<const native_handle_t*>(buffer);
std::lock_guard<std::mutex> lock(mMutex);
@@ -92,9 +99,13 @@
return GrallocImportedBufferPool::getInstance().remove(buffer);
}
- const native_handle_t* getImportedBuffer(void* buffer) const override {
+ native_handle_t* getImportedBuffer(void* buffer) const override {
return GrallocImportedBufferPool::getInstance().get(buffer);
}
+
+ const native_handle_t* getConstImportedBuffer(void* buffer) const override {
+ return GrallocImportedBufferPool::getInstance().getConst(buffer);
+ }
};
class GrallocLoader {
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
index 18fbb6d..8540068 100644
--- a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
@@ -37,6 +37,10 @@
Error validateBufferSize(const native_handle_t* bufferHandle,
const IMapper::BufferDescriptorInfo& descriptorInfo,
uint32_t stride) override {
+ if (descriptorInfo.layerCount != 1) {
+ return Error::BAD_VALUE;
+ }
+
if (!mModule->validateBufferSize) {
return Error::NONE;
}
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 97dab68..cb29c64 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -280,39 +280,50 @@
*/
template <typename ValueT>
class NullOr {
- template <typename T>
- struct reference_initializer {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnull-dereference"
- static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
-#pragma GCC diagnostic pop
- };
- template <typename T>
- struct pointer_initializer {
- static T init() { return nullptr; }
- };
- template <typename T>
- struct value_initializer {
- static T init() { return T(); }
- };
- template <typename T>
- using initializer_t =
- std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
- std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
- value_initializer<T>>>;
+ using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
+ std::remove_reference_t<ValueT>*, ValueT>;
- public:
- NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
- NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
+ struct pointer_initializer {
+ static std::nullptr_t init() { return nullptr; }
+ };
+ struct value_initializer {
+ static ValueT init() { return ValueT(); }
+ };
+ struct value_pointer_deref_t {
+ static ValueT& deref(ValueT& v) { return v; }
+ };
+ struct reference_deref_t {
+ static auto& deref(internal_t v) { return *v; }
+ };
+ using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
+ std::is_pointer<ValueT>::value,
+ pointer_initializer, value_initializer>;
+ using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
+ value_pointer_deref_t>;
+
+ public:
+ NullOr() : value_(initializer_t::init()), null_(true) {}
+ template <typename T>
+ NullOr(T&& value, typename std::enable_if<
+ !std::is_lvalue_reference<ValueT>::value &&
+ std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+ int>::type = 0)
+ : value_(std::forward<ValueT>(value)), null_(false) {}
+ template <typename T>
+ NullOr(T& value, typename std::enable_if<
+ std::is_lvalue_reference<ValueT>::value &&
+ std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+ int>::type = 0)
+ : value_(&value), null_(false) {}
bool isOk() const { return !null_; }
- const ValueT& value() const & { return value_; }
- ValueT& value() & { return value_; }
- ValueT&& value() && { return std::move(value_); }
+ const ValueT& value() const& { return deref_t::deref(value_); }
+ ValueT& value() & { return deref_t::deref(value_); }
+ ValueT&& value() && { return std::move(deref_t::deref(value_)); }
- private:
- ValueT value_;
+ private:
+ internal_t value_;
bool null_;
};
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index 3af1df3..4838e7e 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -48,10 +48,11 @@
SecurityLevel KeymasterHidlTest::securityLevel_;
hidl_string KeymasterHidlTest::name_;
hidl_string KeymasterHidlTest::author_;
+string KeymasterHidlTest::service_name_;
-void KeymasterHidlTest::SetUpTestCase() {
- string service_name = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
- keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
+void KeymasterHidlTest::InitializeKeymaster() {
+ service_name_ = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
+ keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name_);
ASSERT_NE(keymaster_, nullptr);
ASSERT_TRUE(keymaster_
@@ -62,18 +63,22 @@
author_ = author;
})
.isOk());
+}
+
+void KeymasterHidlTest::SetUpTestCase() {
+
+ InitializeKeymaster();
os_version_ = ::keymaster::GetOsVersion();
os_patch_level_ = ::keymaster::GetOsPatchlevel();
auto service_manager = android::hidl::manager::V1_0::IServiceManager::getService();
ASSERT_NE(nullptr, service_manager.get());
-
all_keymasters_.push_back(keymaster_);
service_manager->listByInterface(
IKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
for (auto& name : names) {
- if (name == service_name) continue;
+ if (name == service_name_) continue;
auto keymaster =
::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(name);
ASSERT_NE(keymaster, nullptr);
@@ -269,6 +274,13 @@
return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
}
+ErrorCode KeymasterHidlTest::GetDebugInfo(DebugInfo* debug_info) {
+ EXPECT_TRUE(keymaster_->getDebugInfo([&](const DebugInfo& hidl_debug_info) {
+ *debug_info = hidl_debug_info;
+ }).isOk());
+ return ErrorCode::OK;
+}
+
ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const HidlBuf& key_blob,
const AuthorizationSet& in_params, AuthorizationSet* out_params,
OperationHandle* op_handle) {
@@ -611,6 +623,20 @@
return ciphertext;
}
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+ PaddingMode padding, uint8_t mac_length_bits,
+ const HidlBuf& iv_in) {
+ SCOPED_TRACE("EncryptMessage");
+ auto params = AuthorizationSetBuilder()
+ .BlockMode(block_mode)
+ .Padding(padding)
+ .Authorization(TAG_MAC_LENGTH, mac_length_bits)
+ .Authorization(TAG_NONCE, iv_in);
+ AuthorizationSet out_params;
+ string ciphertext = EncryptMessage(message, params, &out_params);
+ return ciphertext;
+}
+
string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
const AuthorizationSet& params) {
SCOPED_TRACE("DecryptMessage");
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 015fc43..b09da45 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -37,6 +37,7 @@
using ::android::sp;
using ::std::string;
+using hidl::base::V1_0::DebugInfo;
class HidlBuf : public hidl_vec<uint8_t> {
typedef hidl_vec<uint8_t> super;
@@ -95,6 +96,7 @@
// SetUpTestCase runs only once per test case, not once per test.
static void SetUpTestCase();
+ static void InitializeKeymaster();
static void TearDownTestCase() {
keymaster_.clear();
all_keymasters_.clear();
@@ -140,6 +142,8 @@
const HidlBuf& app_data, KeyCharacteristics* key_characteristics);
ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics);
+ ErrorCode GetDebugInfo(DebugInfo* debug_info);
+
ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
AuthorizationSet* out_params, OperationHandle* op_handle);
ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
@@ -201,6 +205,8 @@
HidlBuf* iv_out);
string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
const HidlBuf& iv_in);
+ string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+ uint8_t mac_length_bits, const HidlBuf& iv_in);
string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
const AuthorizationSet& params);
@@ -235,6 +241,7 @@
static SecurityLevel securityLevel_;
static hidl_string name_;
static hidl_string author_;
+ static string service_name_;
};
} // namespace test
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 9e6cce7..0ac7e48 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -18,6 +18,7 @@
#include <cutils/log.h>
#include <iostream>
+#include <signal.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
@@ -2706,6 +2707,40 @@
}
/*
+ * EncryptionOperationsTest.AesWrongPurpose
+ *
+ * Verifies that AES encryption fails in the correct way when an unauthorized purpose is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesWrongPurpose) {
+ auto err = GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesKey(128)
+ .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Padding(PaddingMode::NONE));
+ ASSERT_EQ(ErrorCode::OK, err) << "Got " << err;
+
+ err = Begin(KeyPurpose::DECRYPT,
+ AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE));
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+
+ CheckedDeleteKey();
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesKey(128)
+ .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Padding(PaddingMode::NONE)));
+
+ err = Begin(KeyPurpose::ENCRYPT,
+ AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE));
+ EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+}
+
+/*
* EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize
*
* Verifies that AES encryption fails in the correct way when provided an input that is not a
@@ -3225,6 +3260,92 @@
}
/*
+ * EncryptionOperationsTest.AesGcmRoundTripWithDelaySuccess
+ *
+ * Verifies that AES GCM mode works, even when there's a long delay
+ * between operations.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmRoundTripWithDelaySuccess) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+
+ auto begin_params = AuthorizationSetBuilder()
+ .BlockMode(BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MAC_LENGTH, 128);
+
+ auto update_params =
+ AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+ // Encrypt
+ AuthorizationSet begin_out_params;
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params))
+ << "Begin encrypt";
+ string ciphertext;
+ AuthorizationSet update_out_params;
+ sleep(5);
+ ASSERT_EQ(ErrorCode::OK,
+ Finish(op_handle_, update_params, message, "", &update_out_params, &ciphertext));
+
+ ASSERT_EQ(ciphertext.length(), message.length() + 16);
+
+ // Grab nonce
+ begin_params.push_back(begin_out_params);
+
+ // Decrypt.
+ ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt";
+ string plaintext;
+ size_t input_consumed;
+ sleep(5);
+ ASSERT_EQ(ErrorCode::OK, Update(op_handle_, update_params, ciphertext, &update_out_params,
+ &plaintext, &input_consumed));
+ EXPECT_EQ(ciphertext.size(), input_consumed);
+ sleep(5);
+ EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
+ EXPECT_EQ(message.length(), plaintext.length());
+ EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmDifferentNonces
+ *
+ * Verifies that encrypting the same data with different nonces produces different outputs.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmDifferentNonces) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AesEncryptionKey(128)
+ .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_CALLER_NONCE)));
+
+ string aad = "foobar";
+ string message = "123456789012345678901234567890123456";
+ string nonce1 = "000000000000";
+ string nonce2 = "111111111111";
+ string nonce3 = "222222222222";
+
+ string ciphertext1 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce1));
+ string ciphertext2 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce2));
+ string ciphertext3 =
+ EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce3));
+
+ ASSERT_NE(ciphertext1, ciphertext2);
+ ASSERT_NE(ciphertext1, ciphertext3);
+ ASSERT_NE(ciphertext2, ciphertext3);
+}
+
+/*
* EncryptionOperationsTest.AesGcmTooShortTag
*
* Verifies that AES GCM mode fails correctly when a too-short tag length is specified.
@@ -4456,6 +4577,84 @@
EXPECT_EQ(result, std::make_pair(ErrorCode::OK, HidlBuf()));
}
+
+using ClearOperationsTest = KeymasterHidlTest;
+
+/*
+ * ClearSlotsTest.TooManyOperations
+ *
+ * Verifies that TOO_MANY_OPERATIONS is returned after the max number of
+ * operations are started without being finished or aborted. Also verifies
+ * that aborting the operations clears the operations.
+ *
+ */
+TEST_F(ClearOperationsTest, TooManyOperations) {
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+ int max_operations = SecLevel() == SecurityLevel::STRONGBOX ? 4 : 16;
+ OperationHandle op_handles[max_operations];
+ AuthorizationSet out_params;
+ for(int i=0; i<max_operations; i++) {
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
+ }
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+ // Try again just in case there's a weird overflow bug
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+ for(int i=0; i<max_operations; i++) {
+ EXPECT_EQ(ErrorCode::OK, Abort(op_handles[i]));
+ }
+ EXPECT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+ AbortIfNeeded();
+}
+
+/*
+ * ClearSlotsTest.ServiceDeath
+ *
+ * Verifies that the service is restarted after death and the ongoing
+ * operations are cleared.
+ */
+TEST_F(ClearOperationsTest, ServiceDeath) {
+
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaEncryptionKey(2048, 65537)
+ .Padding(PaddingMode::NONE)));
+
+ auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+ int max_operations = SecLevel() == SecurityLevel::STRONGBOX ? 4 : 16;
+ OperationHandle op_handles[max_operations];
+ AuthorizationSet out_params;
+ for(int i=0; i<max_operations; i++) {
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
+ }
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+
+ DebugInfo debug_info;
+ GetDebugInfo(&debug_info);
+ kill(debug_info.pid, SIGKILL);
+ // wait 1 second for keymaster to restart
+ sleep(1);
+ InitializeKeymaster();
+
+ for(int i=0; i<max_operations; i++) {
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
+ }
+ EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+ Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+ for(int i=0; i<max_operations; i++) {
+ EXPECT_EQ(ErrorCode::OK, Abort(op_handles[i]));
+ }
+}
+
+
} // namespace test
} // namespace V4_0
} // namespace keymaster
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index d07e799..b834132 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -25,7 +25,7 @@
std::cerr << msg << std::endl;
}
-int main() {
+int main(int argc, char* argv[]) {
using ::android::hardware::hidl_vec;
using ::android::hardware::light::V2_0::Brightness;
using ::android::hardware::light::V2_0::Flash;
@@ -41,10 +41,29 @@
return -1;
}
- const static LightState off = {
- .color = 0u, .flashMode = Flash::NONE, .brightnessMode = Brightness::USER,
+ static LightState off = {
+ .color = 0u,
+ .flashMode = Flash::NONE,
+ .brightnessMode = Brightness::USER,
};
+ if (argc > 2) {
+ error("Usage: blank_screen [color]");
+ return -1;
+ }
+
+ if (argc > 1) {
+ char* col_ptr;
+ unsigned int col_new;
+
+ col_new = strtoul(argv[1], &col_ptr, 0);
+ if (*col_ptr != '\0') {
+ error("Failed to convert " + std::string(argv[1]) + " to number");
+ return -1;
+ }
+ off.color = col_new;
+ }
+
service->getSupportedTypes([&](const hidl_vec<Type>& types) {
for (Type type : types) {
Status ret = service->setLight(type, off);
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 02db063..ba9d068 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -25,25 +25,24 @@
* with at least one dimension). Types not prefaced by TENSOR_* represent
* scalar values and must have no dimensions.
*
- * Although many types are defined, most operators accept just a few
+ * Although we define many types, most operators accept just a few
* types. Most used are {@link OperandType::TENSOR_FLOAT32},
* {@link OperandType::TENSOR_QUANT8_ASYMM},
* and {@link OperandType::INT32}.
*/
enum OperandType : int32_t {
/** A 32 bit floating point scalar value. */
- FLOAT32 = 0,
+ FLOAT32 = 0,
/** A signed 32 bit integer scalar value. */
- INT32 = 1,
+ INT32 = 1,
/** An unsigned 32 bit integer scalar value. */
- UINT32 = 2,
-
+ UINT32 = 2,
/** A tensor of 32 bit floating point values. */
- TENSOR_FLOAT32 = 3,
+ TENSOR_FLOAT32 = 3,
/** A tensor of 32 bit integer values. */
- TENSOR_INT32 = 4,
+ TENSOR_INT32 = 4,
/**
- * A tensor of 8 bit integers that represent real numbers.
+ * A tensor of 8 bit unsigned integers that represent real numbers.
*
* Attached to this tensor are two numbers that can be used to convert the
* 8 bit integer to the real value and vice versa. These two numbers are:
@@ -51,21 +50,21 @@
* - zeroPoint: a 32 bit integer, in range [0, 255].
*
* The formula is:
- * real_value = (integer_value - zeroPoint) * scale.
+ * real_value = (integer_value - zeroPoint) * scale.
*/
TENSOR_QUANT8_ASYMM = 5,
/**
- * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
- * OEM operation and data types.
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
*
* OEM specific scalar value.
*/
OEM = 10000,
/**
- * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
- * OEM operation and data types.
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
*
* A tensor of OEM specific values.
*/
@@ -78,7 +77,6 @@
* The type of an operation in a model.
*/
enum OperationType : int32_t {
-
/**
* Adds two tensors, element-wise.
*
@@ -110,14 +108,16 @@
* * 0: A tensor.
* * 1: A tensor of the same {@link OperandType}, and compatible dimensions
* as input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scales and zeroPoint can be different from input0 scale and zeroPoint.
* * 2: An {@link OperandType::INT32} scalar, and has to be one of the
* {@link FusedActivationFunc} values. Specifies the activation to
* invoke on the result.
*
* Outputs:
* * 0: The sum, a tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
ADD = 0,
@@ -187,8 +187,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
AVERAGE_POOL_2D = 1,
@@ -206,22 +206,23 @@
*
* Inputs:
* * 0 ~ n-1: The list of n input tensors, of shape
- * [D0, D1, ..., Daxis(i), ..., Dm]. For inputs of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, all input tensors
- * must have the same scale and zeroPoint.
+ * [D0, D1, ..., Daxis(i), ..., Dm].
+ * All input tensors of
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * must have the same scale and zeroPoint as the output tensor.
* * n: An {@link OperandType::INT32} scalar, specifying the
* concatenation axis.
*
* Outputs:
* * 0: The output, a tensor of the same {@link OperandType} as the input
* tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor, the scale and zeroPoint
+ * values must be the same as the input tensors'.
*/
CONCATENATION = 2,
/**
- * Performs an 2-D convolution operation.
+ * Performs a 2-D convolution operation.
*
* The CONV_2D op sweeps a 2-D filter that can mix channels together over a
* batch of images, applying the filter to each window of each image of the
@@ -238,11 +239,17 @@
* filter[channel, di, dj, k]
* ) + bias[channel]
*
- * Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor {@link OperandType} configurations:
+ * * 32 bit floating point:
+ * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias.
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * * Quantized:
+ * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output.
+ * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
+ * * * input.scale * filter.scale).
+ *
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Both explicit padding and implicit padding are supported.
*
@@ -252,12 +259,12 @@
* * 1: A 4-D tensor, of shape
* [depth_out, filter_height, filter_width, depth_in], specifying the
* filter.
- * * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
- * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
- * should also be of {@link OperandType::TENSOR_FLOAT32}. For input
- * tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias
- * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
- * 0 and bias_scale == input_scale * filter_scale.
+ * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * the bias must be of the same
+ * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+ * of 0 and bias_scale == input_scale * filter_scale.
* * 3: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
* * 4: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -281,11 +288,11 @@
* [depth_out, filter_height, filter_width, depth_in], specifying the
* filter.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
- * also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
- * of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
- * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
- * bias_scale == input_scale * filter_scale.
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * the bias must be of the same
+ * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+ * of 0 and bias_scale == input_scale * filter_scale.
* * 3: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
* following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -299,11 +306,9 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale.
- *
- * Available since API level 27.
+ * [batches, out_height, out_width, depth_out].
+ * For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the following condition must be satisfied: output_scale > input_scale * filter_scale
*/
CONV_2D = 3,
@@ -329,11 +334,17 @@
* filter[1, di, dj, k * channel_multiplier + q]
* ) + bias[k * channel_multiplier + q]
*
- * Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * Supported tensor {@link OperandType} configurations:
+ * * 32 bit floating point:
+ * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias.
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * * Quantized:
+ * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output.
+ * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
+ * * * input.scale * filter.scale).
+ *
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Both explicit padding and implicit padding are supported.
*
@@ -343,11 +354,11 @@
* * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
* specifying the filter.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
- * also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
- * of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
- * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
- * bias_scale == input_scale * filter_scale.
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * the bias must be of the same
+ * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+ * of 0 and bias_scale == input_scale * filter_scale.
* * 3: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
* * 4: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -372,11 +383,11 @@
* * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
* specifying the filter.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
- * also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
- * of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
- * of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
- * bias_scale == input_scale * filter_scale.
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * the bias must be of the same
+ * type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+ * of 0 and bias_scale == input_scale * filter_scale.
* * 3: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
* following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -392,11 +403,10 @@
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. For output tensor of
- * {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
- * must be satisfied: output_scale > input_scale * filter_scale.
- *
- * Available since API level 27.
+ * [batches, out_height, out_width, depth_out]. For
+ * output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the following condition must be satisfied:
+ * output_scale > input_scale * filter_scale
*/
DEPTHWISE_CONV_2D = 4,
@@ -419,7 +429,8 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Inputs:
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -431,8 +442,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape [batch, height*block_size,
* width*block_size, depth/(block_size*block_size)].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
DEPTH_TO_SPACE = 5,
@@ -443,19 +454,19 @@
*
* output = (input - zeroPoint) * scale.
*
- * Supported tensor {@link OperandType}:
+ * Supported input tensor {@link OperandType}:
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
+ * Supported output tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT32}.
+ *
* Supported tensor rank: up to 4
*
* Inputs:
- * * 0: A tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}.
+ * * 0: A tensor.
*
* Outputs:
- * * 0: The output tensor of same shape as input0, but with
- * {@link OperandType::TENSOR_FLOAT32}.
- *
- * Available since API level 27.
+ * * 0: A tensor with the same shape as input0.
*/
DEQUANTIZE = 6,
@@ -479,6 +490,13 @@
* If a value in Lookups is out of bounds, the operation must fail
* and an error must be reported.
*
+ * Supported value tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT32}
+ * * {@link OperandType::TENSOR_INT32}
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ *
+ * Supported value tensor rank: from 2
+ *
* Inputs:
* * 0: Lookups. A 1-D tensor of {@link OperandType::TENSOR_INT32}.
* The values are indices into the first dimension of Values.
@@ -489,8 +507,8 @@
* * 0: A n-D tensor with the same rank and shape as the Values
* tensor, except for the first dimension which has the same size
* as Lookups' only dimension.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input1.
*/
EMBEDDING_LOOKUP = 7,
@@ -508,8 +526,6 @@
* Outputs:
* * 0: The output tensor, of the same {@link OperandType} and dimensions as
* the input tensor.
- *
- * Available since API level 27.
*/
FLOOR = 8,
@@ -549,12 +565,9 @@
* invoke on the result.
*
* Outputs:
- * * 0: The output tensor, of shape [batch_size, num_units]. For output
- * tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
- * condition must be satisfied:
- * output_scale > input_scale * filter_scale.
- *
- * Available since API level 27.
+ * * 0: The output tensor, of shape [batch_size, num_units]. For
+ * output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
+ * condition must be satisfied: output_scale > input_scale * filter_scale.
*/
FULLY_CONNECTED = 9,
@@ -585,6 +598,13 @@
* must be selected. If no entry in Keys has 123456, a slice of zeroes
* must be concatenated.
*
+ * Supported value tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT32}
+ * * {@link OperandType::TENSOR_INT32}
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ *
+ * Supported value tensor rank: from 2
+ *
* Inputs:
* * 0: Lookups. A 1-D {@link OperandType::TENSOR_INT32} tensor with
* shape [ k ].
@@ -598,13 +618,13 @@
*
* Outputs:
* * 0: Output. A tensor with shape [ k …].
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input2.
* * 1: Hits. A boolean tensor with shape [ k ] indicates whether the lookup
* hits (True) or not (False).
* Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0
* and scale 1.0f.
* A non-zero byte represents True, a hit. A zero indicates otherwise.
- *
- * Available since API level 27.
*/
HASHTABLE_LOOKUP = 10,
@@ -617,9 +637,6 @@
* input[batch, row, col, channel] /
* sqrt(sum_{c} pow(input[batch, row, col, c], 2))
*
- * For input tensor with more dimensions, independently normalizes each 1-D
- * slice along dimension dim.
- *
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
@@ -627,13 +644,10 @@
* Height, Width, and Channels).
*
* Inputs:
- * * 0: A 4-D tensor, of shape [batches, height, width, depth].
+ * * 0: A 4-D tensor, specifying the tensor to be normalized.
*
* Outputs:
- * * 0: The output 4-D tensor, of the same shape as input
- * [batches, height, width, depth].
- *
- * Available since API level 27.
+ * * 0: A tensor of the same {@link OperandType} and same shape as input0.
*/
L2_NORMALIZATION = 11,
@@ -652,7 +666,8 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Both explicit padding and implicit padding are supported.
*
@@ -700,8 +715,6 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
*/
L2_POOL_2D = 12,
@@ -729,17 +742,18 @@
* the input.
* * 1: An {@link OperandType::INT32} scalar, specifying the radius of
* the normalization window.
- * * 2: An {@link OperandType::FLOAT32} scalar, specifying the bias, must
- * not be zero.
- * * 3: An {@link OperandType::FLOAT32} scalar, specifying the scale
- * factor, alpha.
- * * 4: An {@link OperandType::FLOAT32} scalar, specifying the exponent,
- * beta.
+ * * 2: A scalar, specifying the bias, must not be zero.
+ * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
+ * value must be of {@link OperandType::FLOAT32}.
+ * * 3: A scalar, specifying the scale factor, alpha.
+ * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the
+ * alpha value must be of {@link OperandType::FLOAT32}.
+ * * 4: A scalar, specifying the exponent, beta.
+ * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the beta
+ * value must be of {@link OperandType::FLOAT32}.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
*/
LOCAL_RESPONSE_NORMALIZATION = 13,
@@ -763,45 +777,53 @@
* * 0: The output tensor of same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 256 and the zeroPoint must be 0.
- *
- * Available since API level 27.
*/
LOGISTIC = 14,
/**
* Projects an input to a bit vector via locality senstive hashing.
*
+ * Supported input tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT32}
+ * * {@link OperandType::TENSOR_INT32}
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ *
+ * Supported input tensor rank: from 1
+ *
* Inputs:
* * 0: Hash functions. Dim.size == 2, DataType: Float.
- * Tensor[0].Dim[0]: Number of hash functions.
- * Tensor[0].Dim[1]: Number of seeds per hash functions.
- * Tensor[0].Dim[1] <= 32 in sparse case.
+ * Tensor[0].Dim[0]: Number of hash functions.
+ * Tensor[0].Dim[1]: Number of projected output bits generated by each
+ * hash function.
+ * If the projection type is Sparse:
+ * Tensor[0].Dim[1] + ceil(log2(Tensor[0].Dim[0])) <= 32
*
* * 1: Input. Dim.size >= 1, no restriction on DataType.
* * 2: Weight. Optional. Dim.size == 1, DataType: Float.
- * If not set, each input element is considered to have the same weight
- * of 1.0.
- * Tensor[1].Dim[0] == Tensor[2].Dim[0]
+ * If not set, each input element is considered to have the same weight
+ * of 1.0.
+ * Tensor[1].Dim[0] == Tensor[2].Dim[0]
* * 3: Type:
- * Sparse: Value LSHProjectionType_SPARSE(=1).
+ * Sparse:
+ * Value LSHProjectionType_SPARSE(=1).
* Computed bit vector is considered to be sparse.
* Each output element is an int32 made up of multiple bits
* computed from hash functions.
*
- * Dense: Value LSHProjectionType_DENSE(=2).
+ * Dense:
+ * Value LSHProjectionType_DENSE(=2).
* Computed bit vector is considered to be dense. Each output
* element represents a bit and can take the value of either
* 0 or 1.
*
* Outputs:
- * * 0: If the projection type is sparse:
- * Output.Dim == { Tensor[0].Dim[0] }
- * A tensor of int32 that represents hash signatures.
- * If the projection type is Dense:
- * Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
- * A flattened tensor that represents projected bit vectors.
+ * * 0: If the projection type is Sparse:
+ * Output.Dim == { Tensor[0].Dim[0] }
+ * A tensor of int32 that represents hash signatures.
*
- * Available since API level 27.
+ * If the projection type is Dense:
+ * Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
+ * A flattened tensor that represents projected bit vectors.
*/
LSH_PROJECTION = 15,
@@ -901,71 +923,54 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
+ * All input and output tensors must be of the same type.
+ *
* Inputs:
* * 0: The input (\f$x_t\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, input_size], where “batch_size” corresponds to the
- * batching dimension, and “input_size” is the size of the input.
+ * A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+ * corresponds to the batching dimension, and “input_size” is the size
+ * of the input.
* * 1: The input-to-input weights (\f$W_{xi}\f$). Optional.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size], where “num_units” corresponds to the
- * number of cell units.
+ * A 2-D tensor of shape [num_units, input_size], where “num_units”
+ * corresponds to the number of cell units.
* * 2: The input-to-forget weights (\f$W_{xf}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size].
+ * A 2-D tensor of shape [num_units, input_size].
* * 3: The input-to-cell weights (\f$W_{xc}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size].
+ * A 2-D tensor of shape [num_units, input_size].
* * 4: The input-to-output weights (\f$W_{xo}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size].
+ * A 2-D tensor of shape [num_units, input_size].
* * 5: The recurrent-to-input weights (\f$W_{hi}\f$). Optional.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, output_size], where “output_size” corresponds to either
- * the number of cell units (i.e., “num_units”), or the second
- * dimension of the “projection_weights”, if defined.
+ * A 2-D tensor of shape [num_units, output_size], where “output_size”
+ * corresponds to either the number of cell units (i.e., “num_units”),
+ * or the second dimension of the “projection_weights”, if defined.
* * 6: The recurrent-to-forget weights (\f$W_{hf}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, output_size].
+ * A 2-D tensor of shape [num_units, output_size].
* * 7: The recurrent-to-cell weights (\f$W_{hc}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, output_size].
+ * A 2-D tensor of shape [num_units, output_size].
* * 8: The recurrent-to-output weights (\f$W_{ho}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, output_size].
+ * A 2-D tensor of shape [num_units, output_size].
* * 9: The cell-to-input weights (\f$W_{ci}\f$). Optional.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 10:The cell-to-forget weights (\f$W_{cf}\f$). Optional.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 11:The cell-to-output weights (\f$W_{co}\f$). Optional.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 12:The input gate bias (\f$b_i\f$). Optional.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 13:The forget gate bias (\f$b_f\f$).
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 14:The cell bias (\f$b_c\f$).
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 15:The output gate bias (\f$b_o\f$).
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 16:The projection weights (\f$W_{proj}\f$). Optional.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [output_size, num_units].
+ * A 2-D tensor of shape [output_size, num_units].
* * 17:The projection bias (\f$b_{proj}\f$). Optional.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [output_size].
+ * A 1-D tensor of shape [output_size].
* * 18:The output state (in) (\f$h_{t-1}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, output_size].
+ * A 2-D tensor of shape [batch_size, output_size].
* * 19:The cell state (in) (\f$C_{t-1}\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, num_units].
* * 20:The activation function (\f$g\f$).
* A value indicating the activation function:
* <ul>
@@ -984,21 +989,15 @@
*
* Outputs:
* * 0: The scratch buffer.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units * 3] with CIFG, or
+ * A 2-D tensor of shape [batch_size, num_units * 3] with CIFG, or
* [batch_size, num_units * 4] without CIFG.
* * 1: The output state (out) (\f$h_t\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, output_size].
+ * A 2-D tensor of shape [batch_size, output_size].
* * 2: The cell state (out) (\f$C_t\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, num_units].
* * 3: The output (\f$o_t\f$).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, output_size]. This is effectively the same as the
- * current “output state (out)” value.
- *
- * Available since API level 27.
+ * A 2-D tensor of shape [batch_size, output_size]. This is effectively
+ * the same as the current “output state (out)” value.
*/
LSTM = 16,
@@ -1019,7 +1018,8 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Both explicit padding and implicit padding are supported.
*
@@ -1067,8 +1067,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
MAX_POOL_2D = 17,
@@ -1106,8 +1106,6 @@
* For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the following condition must be satisfied:
* output_scale > input1_scale * input2_scale.
- *
- * Available since API level 27.
*/
MUL = 18,
@@ -1129,8 +1127,8 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU = 19,
@@ -1151,9 +1149,9 @@
* * 0: A tensor, specifying the input.
*
* Outputs:
- * * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * * 0: The output tensor of the same shape as input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU1 = 20,
@@ -1175,8 +1173,8 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU6 = 21,
@@ -1205,8 +1203,8 @@
*
* Outputs:
* * 0: The output tensor, of shape specified by the input shape.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RESHAPE = 22,
@@ -1220,9 +1218,10 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
- * Inputs:
+ * Inputs (resizing by shape):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
* the input.
* * 1: An {@link OperandType::INT32} scalar, specifying the output
@@ -1233,8 +1232,6 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, new_height, new_width, depth].
- *
- * Available since API level 27.
*/
RESIZE_BILINEAR = 23,
@@ -1257,25 +1254,23 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
+ * The input tensors must all be the same type.
+ *
* Inputs:
* * 0: input.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32} of shape
- * [batch_size, input_size], where “batch_size” corresponds to the
- * batching dimension, and “input_size” is the size of the input.
+ * A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+ * corresponds to the batching dimension, and “input_size” is the size
+ * of the input.
* * 1: weights.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size], where “num_units” corresponds to the
- * number of units.
+ * A 2-D tensor of shape [num_units, input_size], where “num_units”
+ * corresponds to the number of units.
* * 2: recurrent_weights.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, num_units], with columns corresponding to the weights
- * from each unit.
+ * A 2-D tensor of shape [num_units, num_units], with columns
+ * corresponding to the weights from each unit.
* * 3: bias.
- * A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units].
+ * A 1-D tensor of shape [num_units].
* * 4: hidden state (in).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, num_units].
* * 5: fused_activation_function.
* An optional {@link FusedActivationFunc} value indicating the
* activation function. If “NONE” is specified then it results in a
@@ -1283,15 +1278,11 @@
*
* Outputs:
* * 0: hidden state (out).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units].
+ * A 2-D tensor of shape [batch_size, num_units].
*
* * 1: output.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, num_units]. This is effectively the same as the
- * current state value.
- *
- * Available since API level 27.
+ * A 2-D tensor of shape [batch_size, num_units]. This is effectively
+ * the same as the current state value.
*/
RNN = 24,
@@ -1306,6 +1297,9 @@
* exp((input[batch, i] - max(input[batch, :])) * beta) /
* sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)}
*
+ * For input tensor with rank other than 2, the activation will be applied
+ * independently on each 1-D slice along specified dimension.
+ *
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
@@ -1314,15 +1308,15 @@
*
* Inputs:
* * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
- * * 1: An {@link OperandType::FLOAT32} scalar, specifying the positive
- * scaling factor for the exponent, beta.
+ * * 1: A scalar, specifying the positive scaling factor for the exponent,
+ * beta. If input0 is of {@link OperandType::TENSOR_FLOAT32} or
+ * {@link OperandType::TENSOR_QUANT8_ASYMM}, the scalar must be of
+ * {@link OperandType::FLOAT32}.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 256 and the zeroPoint must be 0.
- *
- * Available since API level 27.
*/
SOFTMAX = 25,
@@ -1344,7 +1338,8 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
- * Supported tensor rank: 4, with "NHWC" data layout.
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Inputs:
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -1356,8 +1351,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape [batches, height/block_size,
* width/block_size, depth_in*block_size*block_size].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SPACE_TO_DEPTH = 26,
@@ -1403,25 +1398,23 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
*
+ * All input tensors must be the same type.
+ *
* Inputs:
* * 0: input.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, input_size], where “batch_size” corresponds to the
- * batching dimension, and “input_size” is the size of the input.
+ * A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+ * corresponds to the batching dimension, and “input_size” is the size
+ * of the input.
* * 1: weights_feature.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, input_size], where “num_units” corresponds to the
- * number of units.
+ * A 2-D tensor of shape [num_units, input_size], where “num_units”
+ * corresponds to the number of units.
* * 2: weights_time.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [num_units, memory_size], where “memory_size” corresponds to the
- * fixed-size of the memory.
+ * A 2-D tensor of shape [num_units, memory_size], where “memory_size”
+ * corresponds to the fixed-size of the memory.
* * 3: bias.
- * An optional 1-D tensor of {@link OperandType::TENSOR_FLOAT32},
- * of shape [num_units].
+ * An optional 1-D tensor of shape [num_units].
* * 4: state (in).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
- * [batch_size, (memory_size - 1) * num_units * rank].
+ * A 2-D tensor of shape [batch_size, (memory_size - 1) * num_units * rank].
* * 5: rank.
* The rank of the SVD approximation.
* * 6: fused_activation_function.
@@ -1431,13 +1424,11 @@
*
* Outputs:
* * 0: state (out).
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
+ * A 2-D tensor of the same {@link OperandType} as the inputs, with shape
* [batch_size, (memory_size - 1) * num_units * rank].
* * 1: output.
- * A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
+ * A 2-D tensor of the same {@link OperandType} as the inputs, with shape
* [batch_size, num_units].
- *
- * Available since API level 27.
*/
SVDF = 27,
@@ -1458,8 +1449,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
*/
TANH = 28,
diff --git a/neuralnetworks/1.0/types.t b/neuralnetworks/1.0/types.t
new file mode 100644
index 0000000..d7b26aa
--- /dev/null
+++ b/neuralnetworks/1.0/types.t
@@ -0,0 +1,431 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * Copyright (C) 2017 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.neuralnetworks@1.0;
+
+%insert Operand_1.0_Comment
+enum OperandType : int32_t {
+%insert Operand_1.0
+
+ /**
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
+ *
+ * OEM specific scalar value.
+ */
+ OEM = 10000,
+
+ /**
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
+ *
+ * A tensor of OEM specific values.
+ */
+ TENSOR_OEM_BYTE = 10001,
+};
+
+%insert Operation_1.0_Comment
+enum OperationType : int32_t {
+%insert Operation_1.0
+
+ /**
+ * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+ * OEM operation and data types.
+ *
+ * This operation is OEM specific. It should only be used for OEM
+ * applications.
+ */
+ OEM_OPERATION = 10000,
+};
+
+/**
+ * Fused activation function types.
+ */
+enum FusedActivationFunc : int32_t {
+ NONE = 0,
+ RELU = 1,
+ RELU1 = 2,
+ RELU6 = 3,
+};
+
+/**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+ /**
+ * The operand is internal to the model. It's created by an operation and
+ * consumed by other operations. It must be an output operand of
+ * exactly one operation.
+ */
+ TEMPORARY_VARIABLE,
+
+ /**
+ * The operand is an input of the model. It must not be an output
+ * operand of any operation.
+ *
+ * An operand can't be both input and output of a model.
+ */
+ MODEL_INPUT,
+
+ /**
+ * The operand is an output of the model. It must be an output
+ * operand of exactly one operation.
+ *
+ * An operand can't be both input and output of a model.
+ */
+ MODEL_OUTPUT,
+
+ /**
+ * The operand is a constant found in Model.operandValues. It must
+ * not be an output operand of any operation.
+ */
+ CONSTANT_COPY,
+
+ /**
+ * The operand is a constant that was specified via a Memory
+ * object. It must not be an output operand of any operation.
+ */
+ CONSTANT_REFERENCE,
+
+ /**
+ * The operand does not have a value. This is valid only for optional
+ * arguments of operations.
+ */
+ NO_VALUE,
+};
+
+/**
+ * Status of a device.
+ */
+enum DeviceStatus : int32_t {
+ AVAILABLE,
+ BUSY,
+ OFFLINE,
+ UNKNOWN,
+};
+
+/**
+ * Performance information for the reference workload.
+ *
+ * Used by a driver to report its performance characteristics.
+ */
+struct PerformanceInfo {
+ /**
+ * Ratio of the time taken by the driver to execute the
+ * workload compared to the time the CPU would take for the
+ * same workload. A lower number is better.
+ */
+ float execTime;
+
+ /**
+ * Ratio of the energy used by the driver compared to what
+ * the CPU would use for doing the same workload. A lower number
+ * is better.
+ */
+ float powerUsage;
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+ /**
+ * Driver performance when operating on float32 data.
+ */
+ PerformanceInfo float32Performance;
+
+ /**
+ * Driver performance when operating on asymmetric 8-bit quantized data.
+ */
+ PerformanceInfo quantized8Performance;
+};
+
+/**
+ * Describes the location of a data object.
+ */
+struct DataLocation {
+ /**
+ * The index of the memory pool where this location is found.
+ */
+ uint32_t poolIndex;
+
+ /**
+ * Offset in bytes from the start of the pool.
+ */
+ uint32_t offset;
+
+ /**
+ * The length of the data in bytes.
+ */
+ uint32_t length;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+ /**
+ * Data type of the operand.
+ */
+ OperandType type;
+
+ /**
+ * Dimensions of the operand.
+ *
+ * For a scalar operand, dimensions.size() must be 0.
+ *
+ * For a tensor operand, dimensions.size() must be at least 1;
+ * however, any of the dimensions may be unspecified.
+ *
+ * A tensor operand with all dimensions specified has "fully
+ * specified" dimensions. Whenever possible (i.e., whenever the
+ * dimensions are known at model construction time), a tensor
+ * operand should have (but is not required to have) fully
+ * specified dimensions, in order to enable the best possible
+ * performance.
+ *
+ * If a tensor operand's dimensions are not fully specified, the
+ * dimensions of the operand are deduced from the operand
+ * dimensions and values of the operation for which that operand
+ * is an output.
+ *
+ * In the following situations, a tensor operand's dimensions must
+ * be fully specified:
+ *
+ * . The operand has lifetime CONSTANT_COPY or
+ * CONSTANT_REFERENCE.
+ *
+ * . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+ * specified dimensions must either be present in the
+ * Operand or they must be provided in the corresponding
+ * RequestArgument.
+ * EXCEPTION: If the input or output is optional and omitted
+ * (by setting the hasNoValue field of the corresponding
+ * RequestArgument to true) then it need not have fully
+ * specified dimensions.
+ *
+ * A tensor operand with some number of unspecified dimensions is
+ * represented by setting each unspecified dimension to 0.
+ */
+ vec<uint32_t> dimensions;
+
+ /**
+ * The number of times this operand appears as an operation input.
+ *
+ * (For example, if this operand appears once in one operation's
+ * input list, and three times in another operation's input list,
+ * then numberOfConsumers = 4.)
+ */
+ uint32_t numberOfConsumers;
+
+ /**
+ * Quantized scale of the operand.
+ *
+ * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+ * TENSOR_INT32.
+ */
+ float scale;
+
+ /**
+ * Quantized zero-point offset of the operand.
+ *
+ * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ */
+ int32_t zeroPoint;
+
+ /**
+ * How the operand is used.
+ */
+ OperandLifeTime lifetime;
+
+ /**
+ * Where to find the data for this operand.
+ * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+ * NO_VALUE:
+ * - All the fields must be 0.
+ * If the lifetime is CONSTANT_COPY:
+ * - location.poolIndex is 0.
+ * - location.offset is the offset in bytes into Model.operandValues.
+ * - location.length is set.
+ * If the lifetime is CONSTANT_REFERENCE:
+ * - location.poolIndex is set.
+ * - location.offset is the offset in bytes into the specified pool.
+ * - location.length is set.
+ */
+ DataLocation location;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+ /**
+ * The operation type.
+ */
+ OperationType type;
+
+ /**
+ * Describes the table that contains the indexes of the inputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> inputs;
+
+ /**
+ * Describes the table that contains the indexes of the outputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * might not be known is the shape of the input tensors.
+ */
+struct Model {
+ /**
+ * All operands included in the model.
+ */
+ vec<Operand> operands;
+
+ /**
+ * All operations included in the model.
+ *
+ * The operations are sorted into execution order. Every operand
+ * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+ * written before it is read.
+ */
+ vec<Operation> operations;
+
+ /**
+ * Input indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> inputIndexes;
+
+ /**
+ * Output indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> outputIndexes;
+
+ /**
+ * A byte buffer containing operand data that were copied into the model.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_COPY.
+ */
+ vec<uint8_t> operandValues;
+
+ /**
+ * A collection of shared memory pools containing operand values.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_REFERENCE.
+ */
+ vec<memory> pools;
+};
+
+/**
+ * Metadata information specifying the location of the input or output data and
+ * any updates to the input or output operand.
+ */
+struct RequestArgument {
+ /**
+ * If true, the argument does not have a value. This can be used for
+ * operations that take optional arguments. If true, the fields of location
+ * are set to 0 and the dimensions vector is left empty.
+ */
+ bool hasNoValue;
+
+ /**
+ * The location within one of the memory pools passed in the Request.
+ */
+ DataLocation location;
+
+ /**
+ * Updated dimension information.
+ *
+ * If dimensions.size() > 0, dimension information was provided
+ * along with the argument. This can be the case for models that
+ * accept inputs of varying size. This can't change the rank, just
+ * the value of the dimensions that were unspecified in the
+ * model. If dimensions.size() > 0, then all dimensions must be
+ * specified here; and any dimension that was specified in the
+ * model must have the same value here.
+ *
+ * If the dimensions in the model are not fully specified, then
+ * they must be fully specified here, unless hasNoValue is set to
+ * true. If the dimensions in the model are fully specified, then
+ * either dimensions.size() may be 0, or the dimensions in the
+ * model must be identical to the dimensions here.
+ */
+ vec<uint32_t> dimensions;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 1) Provides the input and output data to be used when executing the model.
+ * 2) Specifies any updates to the input operand metadata that were left
+ * unspecified at model preparation time.
+ *
+ * An output must not overlap with any other output, with an input, or
+ * with an operand of lifetime CONSTANT_REFERENCE.
+ */
+struct Request {
+ /**
+ * Input data and information to be used in the execution of a prepared
+ * model.
+ *
+ * The index of the input corresponds to the index in Model.inputIndexes.
+ * E.g., input[i] corresponds to Model.inputIndexes[i].
+ */
+ vec<RequestArgument> inputs;
+
+ /**
+ * Output data and information to be used in the execution of a prepared
+ * model.
+ *
+ * The index of the output corresponds to the index in Model.outputIndexes.
+ * E.g., output[i] corresponds to Model.outputIndexes[i].
+ */
+ vec<RequestArgument> outputs;
+
+ /**
+ * A collection of shared memory pools containing operand data for both the
+ * inputs and the outputs to a model.
+ */
+ vec<memory> pools;
+};
+
+/**
+ * Return status of a function.
+ */
+enum ErrorStatus : int32_t {
+ NONE,
+ DEVICE_UNAVAILABLE,
+ GENERAL_FAILURE,
+ OUTPUT_INSUFFICIENT_SIZE,
+ INVALID_ARGUMENT,
+};
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 73705bb..3d78fb6 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -26,7 +26,6 @@
* The type of an operation in a model.
*/
enum OperationType : @1.0::OperationType {
-
/**
* BatchToSpace for N-dimensional tensors.
*
@@ -41,7 +40,8 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
- * Supported tensor rank: 4
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Inputs:
* * 0: An n-D tensor, specifying the tensor to be reshaped
@@ -51,8 +51,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
BATCH_TO_SPACE_ND = 29,
@@ -91,8 +91,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
*/
DIV = 30,
@@ -126,8 +124,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be same as input0.
*/
MEAN = 31,
@@ -138,7 +136,8 @@
*
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (the pad value is undefined)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * (the pad value is undefined)
*
* Supported tensor rank: up to 4
*
@@ -160,11 +159,8 @@
* of the padding:
* output0.dimension[i] =
* padding[i, 0] + input0.dimension[i] + padding[i, 1]
- *
- * NOTE: The pad value for {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
- * is undefined.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
PAD = 32,
@@ -182,8 +178,10 @@
* Supported tensor {@link OperandType}:
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * (the pad value is undefined)
*
- * Supported tensor rank: 4
+ * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+ * and Channels) data layout.
*
* Inputs:
* * 0: An n-D tensor, specifying the input.
@@ -201,8 +199,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SPACE_TO_BATCH_ND = 33,
@@ -232,8 +230,8 @@
* * 0: A tensor of the same {@link OperandType} as input0. Contains the
* same data as input, but has one or more dimensions of size 1
* removed.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SQUEEZE = 34,
@@ -278,8 +276,8 @@
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
* where k is the number of bits set in shrink_axis_mask.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
STRIDED_SLICE = 35,
@@ -318,8 +316,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
*/
SUB = 36,
@@ -345,11 +341,10 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
TRANSPOSE = 37,
-
};
/**
diff --git a/neuralnetworks/1.1/types.t b/neuralnetworks/1.1/types.t
new file mode 100644
index 0000000..75ac2e7
--- /dev/null
+++ b/neuralnetworks/1.1/types.t
@@ -0,0 +1,158 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * Copyright (C) 2018 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.neuralnetworks@1.1;
+
+import @1.0::Operand;
+import @1.0::OperationType;
+import @1.0::PerformanceInfo;
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.0::OperationType {
+%insert Operation_1.1
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+ /**
+ * Driver performance when operating on float32 data.
+ */
+ PerformanceInfo float32Performance;
+
+ /**
+ * Driver performance when operating on asymmetric 8-bit quantized data.
+ */
+ PerformanceInfo quantized8Performance;
+
+ /**
+ * Driver performance when operating on float32 data but performing
+ * calculations with range and/or precision as low as that of the IEEE
+ * 754 16-bit floating-point format.
+ */
+ PerformanceInfo relaxedFloat32toFloat16Performance;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+ /**
+ * The operation type.
+ */
+ OperationType type;
+
+ /**
+ * Describes the table that contains the indexes of the inputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> inputs;
+
+ /**
+ * Describes the table that contains the indexes of the outputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+ /**
+ * All operands included in the model.
+ */
+ vec<Operand> operands;
+
+ /**
+ * All operations included in the model.
+ *
+ * The operations are sorted into execution order. Every operand
+ * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+ * written before it is read.
+ */
+ vec<Operation> operations;
+
+ /**
+ * Input indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> inputIndexes;
+
+ /**
+ * Output indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> outputIndexes;
+
+ /**
+ * A byte buffer containing operand data that were copied into the model.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_COPY.
+ */
+ vec<uint8_t> operandValues;
+
+ /**
+ * A collection of shared memory pools containing operand values.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_REFERENCE.
+ */
+ vec<memory> pools;
+
+ /**
+ * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
+ * precision as low as that of the IEEE 754 16-bit floating-point format.
+ * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
+ * range and precision of the IEEE 754 32-bit floating-point format.
+ */
+ bool relaxComputationFloat32toFloat16;
+};
+
+/**
+ * Execution preferences.
+ */
+enum ExecutionPreference : int32_t {
+ /**
+ * Prefer executing in a way that minimizes battery drain.
+ * This is desirable for compilations that will be executed often.
+ */
+ LOW_POWER = 0,
+ /**
+ * Prefer returning a single answer as fast as possible, even if this causes
+ * more power consumption.
+ */
+ FAST_SINGLE_ANSWER = 1,
+ /**
+ * Prefer maximizing the throughput of successive frames, for example when
+ * processing successive frames coming from the camera.
+ */
+ SUSTAINED_SPEED = 2,
+};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index f368ce2..837ced5 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -43,8 +43,6 @@
*
* Values of this operand type are either true or false. A zero value
* represents false; any other value represents true.
- *
- * Available since API level 29.
*/
BOOL = 6,
/**
@@ -55,14 +53,10 @@
* realValue = integerValue * scale.
*
* scale is a 32 bit floating point with value greater than zero.
- *
- * Available since API level 29.
*/
TENSOR_QUANT16_SYMM = 7,
/**
* A tensor of IEEE 754 16 bit floating point values.
- *
- * Available since API level 29.
*/
TENSOR_FLOAT16 = 8,
/**
@@ -70,14 +64,10 @@
*
* Values of this operand type are either true or false. A zero value
* represents false; any other value represents true.
- *
- * Available since API level 29.
*/
TENSOR_BOOL8 = 9,
/**
* An IEEE 754 16 bit floating point scalar value.
- *
- * Available since API level 29.
*/
FLOAT16 = 10,
/**
@@ -90,14 +80,13 @@
* - scales: an array of positive 32 bit floating point values.
* The size of the scales array must be equal to dimensions[channelDim].
*
+ *{@link SymmPerChannelQuantParams} must hold the parameters for an Operand of this type.
* The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
*
* The formula is:
* realValue[..., C, ...] =
* integerValue[..., C, ...] * scales[C]
* where C is an index in the Channel dimension.
- *
- * Available since API level 29.
*/
TENSOR_QUANT8_SYMM_PER_CHANNEL = 11,
/**
@@ -110,8 +99,6 @@
*
* The formula is:
* real_value = (integer_value - zeroPoint) * scale.
- *
- * Available since API level 29.
*/
TENSOR_QUANT16_ASYMM = 12,
/**
@@ -122,20 +109,19 @@
* realValue = integerValue * scale.
*
* scale is a 32 bit floating point with value greater than zero.
- *
- * Available since API level 29.
*/
TENSOR_QUANT8_SYMM = 13,
+
/*
- * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
- * OEM operation and data types.
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
*
* OEM specific scalar value.
* OEM = 10000,
*/
/*
- * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
- * OEM operation and data types.
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
*
* A tensor of OEM specific values.
* TENSOR_OEM_BYTE = 10001,
@@ -166,6 +152,7 @@
* The type of an operation in a model.
*/
enum OperationType : int32_t {
+
/**
* Adds two tensors, element-wise.
*
@@ -187,12 +174,12 @@
* input2.dimension = {5, 4, 3, 1}
* output.dimension = {5, 4, 3, 2}
*
- * Since API level 29, generic zero-sized input tensor is supported. Zero
+ * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
* dimension is only compatible with 0 or 1. The size of the output
* dimension is zero if either of corresponding input dimension is zero.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -202,14 +189,16 @@
* * 0: A tensor.
* * 1: A tensor of the same {@link OperandType}, and compatible dimensions
* as input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scales and zeroPoint can be different from input0 scale and zeroPoint.
* * 2: An {@link OperandType::INT32} scalar, and has to be one of the
* {@link FusedActivationFunc} values. Specifies the activation to
* invoke on the result.
*
* Outputs:
* * 0: The sum, a tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
ADD = @1.1::OperationType:ADD,
@@ -227,7 +216,7 @@
* ) / sum(1)
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -235,13 +224,14 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both explicit padding and implicit padding are supported.
*
* Inputs (explicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
* * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -263,12 +253,12 @@
* invoke on the result.
* * 10: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Inputs (implicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
* following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -285,13 +275,13 @@
* invoke on the result.
* * 7: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
AVERAGE_POOL_2D = @1.1::OperationType:AVERAGE_POOL_2D,
@@ -302,33 +292,34 @@
* dimensions except the dimension along the concatenation axis.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API
- * level 29, see the input section)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * (full support since HAL version 1.2, see the input section)
*
* Supported tensor rank: up to 4
*
* Inputs:
* * 0 ~ n-1: The list of n input tensors, of shape
* [D0, D1, ..., Daxis(i), ..., Dm].
- * Before API level 29, all input tensors of
+ * Before HAL version 1.2, all input tensors of
* {@link OperandType::TENSOR_QUANT8_ASYMM}
* must have the same scale and zeroPoint as the output tensor.
- * Since API level 29, zero-sized tensors are supported.
+ * Since HAL version 1.2, zero-sized tensors are supported.
* * n: An {@link OperandType::INT32} scalar, specifying the
* concatenation axis.
*
* Outputs:
* * 0: The output, a tensor of the same {@link OperandType} as the input
* tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
- *
- * Available since API level 27.
+ * Since HAL version 1.2, for a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint values can be different from
+ * input tensors. Before HAL version 1.2 they have to be the same as for the input tensors.
*/
CONCATENATION = @1.1::OperationType:CONCATENATION,
/**
- * Performs an 2-D convolution operation.
+ * Performs a 2-D convolution operation.
*
* The CONV_2D op sweeps a 2-D filter that can mix channels together over a
* batch of images, applying the filter to each window of each image of the
@@ -354,7 +345,7 @@
* * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
* * * input.scale * filter.scale).
*
- * Available since API level 29:
+ * Available since HAL version 1.2:
* * 16 bit floating point:
* * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
*
@@ -368,27 +359,29 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both explicit padding and implicit padding are supported.
*
* Inputs (explicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
- * specifying the input. Since API level 29, zero batches is supported
- * for this tensor.
+ * specifying the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: A 4-D tensor, of shape
* [depth_out, filter_height, filter_width, depth_in], specifying the
- * filter. For tensor of type
- * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
- * dimension (extraParams.channelQuant.channelDim) must be set to 0.
+ * filter.
+ * For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+ * the channel dimension (SymmPerChannelQuantParams::channelDim)
+ * must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of type {@link OperandType::TENSOR_FLOAT32} or
- * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
* type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
- * of 0 and bias_scale == input_scale * filter_scale. For filter tensor
- * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
- * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
- * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+ * of 0 and bias_scale == input_scale * filter_scale.
+ * For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+ * and bias_scale of 0. The actual scale of each value 'i' is equal to
* bias_scale[i] = input_scale * filter_scale[i].
* * 3: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
@@ -407,36 +400,37 @@
* invoke on the result.
* * 10: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 11: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on width dimension. If this input is set,
* input 12 (dilation factor for height) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on height dimension. If this input is set,
* input 11 (dilation factor for width) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Inputs (implicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
- * specifying the input. Since API level 29, zero batches is supported
- * for this tensor.
+ * specifying the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: A 4-D tensor, of shape
* [depth_out, filter_height, filter_width, depth_in], specifying the
- * filter. For tensor of type
- * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
- * dimension (extraParams.channelQuant.channelDim) must be set to 0.
+ * filter.
+ * For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+ * the channel dimension (SymmPerChannelQuantParams::channelDim)
+ * must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of type {@link OperandType::TENSOR_FLOAT32} or
- * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
* type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
- * of 0 and bias_scale == input_scale * filter_scale. For filter tensor
- * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
- * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
- * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+ * of 0 and bias_scale == input_scale * filter_scale.
+ * For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+ * and bias_scale of 0. The actual scale of each value 'i' is equal to
* bias_scale[i] = input_scale * filter_scale[i].
* * 3: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
@@ -450,26 +444,23 @@
* invoke on the result.
* * 7: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 8: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on width dimension. If this input is set,
* input 9 (dilation factor for height) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on height dimension. If this input is set,
* input 8 (dilation factor for width) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. Before API level 29,
- * for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
- * following condition must be satisfied:
- * output_scale > input_scale * filter_scale
- *
- * Available since API level 27.
+ * [batches, out_height, out_width, depth_out].
+ * Before HAL version 1.2, for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the following condition must be satisfied: output_scale > input_scale * filter_scale
*/
CONV_2D = @1.1::OperationType:CONV_2D,
@@ -504,7 +495,7 @@
* * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
* * * input.scale * filter.scale).
*
- * Available since API level 29:
+ * Available since HAL version 1.2:
* * 16 bit floating point:
* * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
*
@@ -518,6 +509,7 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both explicit padding and implicit padding are supported.
*
@@ -525,18 +517,19 @@
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
* specifying the input.
* * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
- * specifying the filter. For tensor of type
- * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
- * dimension (extraParams.channelQuant.channelDim) must be set to 3.
+ * specifying the filter.
+ * For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+ * the channel dimension (SymmPerChannelQuantParams::channelDim)
+ * must be set to 3.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of type {@link OperandType::TENSOR_FLOAT32} or
- * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
* type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
- * of 0 and bias_scale == input_scale * filter_scale. For filter tensor
- * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
- * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
- * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+ * of 0 and bias_scale == input_scale * filter_scale.
+ * For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+ * and bias_scale of 0. The actual scale of each value 'i' is equal to
* bias_scale[i] = input_scale * filter_scale[i].
* * 3: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
@@ -557,17 +550,17 @@
* invoke on the result.
* * 11: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on width dimension. If this input is set,
* input 13 (dilation factor for height) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 13: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on height dimension. If this input is set,
* input 12 (dilation factor for width) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Inputs (implicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -575,14 +568,14 @@
* * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
* specifying the filter.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
- * tensor of type {@link OperandType::TENSOR_FLOAT32} or
- * {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+ * tensor of type {@link OperandType::TENSOR_FLOAT32}
+ * or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
* type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
- * of 0 and bias_scale == input_scale * filter_scale. For filter tensor
- * of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
- * should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
- * 0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+ * of 0 and bias_scale == input_scale * filter_scale.
+ * For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+ * the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+ * and bias_scale of 0. The actual scale of each value 'i' is equal to
* bias_scale[i] = input_scale * filter_scale[i].
* * 3: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
@@ -598,27 +591,24 @@
* invoke on the result.
* * 8: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on width dimension. If this input is set,
* input 10 (dilation factor for height) must be specified as well.
- * Available since API level 29.
+ * Available since HAL version 1.2.
* * 10: An optional {@link OperandType::INT32} scalar, specifying the dilation
* factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
* cells between each filter element on height dimension. If this input is set,
* input 9 (dilation factor for width) must be specified as well.
- * Available since API level 29.
-
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape
- * [batches, out_height, out_width, depth_out]. Before API level 29,
- * for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
- * following condition must be satisfied:
+ * [batches, out_height, out_width, depth_out]. Before HAL version 1.2, for
+ * output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+ * the following condition must be satisfied:
* output_scale > input_scale * filter_scale
- *
- * Available since API level 27.
*/
DEPTHWISE_CONV_2D = @1.1::OperationType:DEPTHWISE_CONV_2D,
@@ -638,7 +628,7 @@
* be divisible by block_size * block_size
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -646,6 +636,7 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Inputs:
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -655,13 +646,13 @@
* of the input depth.
* * 2: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape [batch, height*block_size,
* width*block_size, depth/(block_size*block_size)].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
DEPTH_TO_SPACE = @1.1::OperationType:DEPTH_TO_SPACE,
@@ -674,22 +665,21 @@
*
* Supported input tensor {@link OperandType}:
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
- * * {@link OperandType::TENSOR_QUANT8_SYMM} (since API level 29)
- * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} (since API level 29)
+ * * {@link OperandType::TENSOR_QUANT8_SYMM} (since HAL version 1.2)
+ * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} (since HAL version 1.2)
*
* Supported output tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}.
*
* Supported tensor rank: up to 4
*
* Inputs:
- * * 0: A tensor. Since API level 29, this tensor may be zero-sized.
+ * * 0: A tensor.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
* * 0: A tensor with the same shape as input0.
- *
- * Available since API level 27.
*/
DEQUANTIZE = @1.1::OperationType:DEQUANTIZE,
@@ -730,8 +720,8 @@
* * 0: A n-D tensor with the same rank and shape as the Values
* tensor, except for the first dimension which has the same size
* as Lookups' only dimension.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input1.
*/
EMBEDDING_LOOKUP = @1.1::OperationType:EMBEDDING_LOOKUP,
@@ -739,7 +729,7 @@
* Computes element-wise floor() on the input tensor.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* Supported tensor rank: up to 4
@@ -750,8 +740,6 @@
* Outputs:
* * 0: The output tensor, of the same {@link OperandType} and dimensions as
* the input tensor.
- *
- * Available since API level 27.
*/
FLOOR = @1.1::OperationType:FLOOR,
@@ -764,7 +752,7 @@
* outputs = activation(inputs * weights’ + bias)
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -777,8 +765,8 @@
* [batch_size, input_size], where "input_size" corresponds to the
* number of inputs to the layer, matching the second dimension of
* weights, and "batch_size" is calculated by dividing the number of
- * elements by "input_size". Since API level 29, zero batch_size is
- * supported for this tensor.
+ * elements by "input_size".
+ * Since HAL version 1.2, zero batch_size is supported for this tensor.
* * 1: A 2-D tensor, specifying the weights, of shape
* [num_units, input_size], where "num_units" corresponds to the number
* of output nodes.
@@ -793,12 +781,9 @@
* invoke on the result.
*
* Outputs:
- * * 0: The output tensor, of shape [batch_size, num_units]. Before API
- * level 29, For output tensor of {@link
- * OperandType::TENSOR_QUANT8_ASYMM}, the following condition must be
- * satisfied: output_scale > input_scale * filter_scale.
- *
- * Available since API level 27.
+ * * 0: The output tensor, of shape [batch_size, num_units]. Before HAL version 1.2, for
+ * output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
+ * condition must be satisfied: output_scale > input_scale * filter_scale.
*/
FULLY_CONNECTED = @1.1::OperationType:FULLY_CONNECTED,
@@ -849,13 +834,13 @@
*
* Outputs:
* * 0: Output. A tensor with shape [ k …].
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input2.
* * 1: Hits. A boolean tensor with shape [ k ] indicates whether the lookup
* hits (True) or not (False).
* Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0
* and scale 1.0f.
* A non-zero byte represents True, a hit. A zero indicates otherwise.
- *
- * Available since API level 27.
*/
HASHTABLE_LOOKUP = @1.1::OperationType:HASHTABLE_LOOKUP,
@@ -872,12 +857,12 @@
* 1-D slice along dimension dim.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
*
* Supported tensor rank: up to 4
- * Tensors with rank less than 4 are only supported since API level 29.
+ * Tensors with rank less than 4 are only supported since HAL version 1.2.
*
* Inputs:
* * 0: An n-D tensor, specifying the tensor to be normalized.
@@ -885,14 +870,12 @@
* specifying the dimension normalization would be performed on.
* Negative index is used to specify axis from the end (e.g. -1 for
* the last axis). Must be in the range [-n, n).
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} and same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 128 and the zeroPoint must be 128.
- *
- * Available since API level 27.
*/
L2_NORMALIZATION = @1.1::OperationType:L2_NORMALIZATION,
@@ -909,20 +892,21 @@
* sum(1))
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both explicit padding and implicit padding are supported.
*
* Inputs (explicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
* * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -944,12 +928,12 @@
* invoke on the result.
* * 10: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Inputs (implicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
* following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -966,13 +950,11 @@
* invoke on the result.
* * 7: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
*/
L2_POOL_2D = @1.1::OperationType:L2_POOL_2D,
@@ -994,11 +976,11 @@
* 1-D slice along specified dimension.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* Supported tensor rank: up to 4
- * Tensors with rank less than 4 are only supported since API level 29.
+ * Tensors with rank less than 4 are only supported since HAL version 1.2.
*
* Inputs:
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
@@ -1011,10 +993,10 @@
* For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
* value must be of {@link OperandType::FLOAT32}.
* * 3: A scalar, specifying the scale factor, alpha.
- * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the alpha
- * value must be of {@link OperandType::FLOAT16}.
- * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the alpha
- * value must be of {@link OperandType::FLOAT32}.
+ * For input tensor of {@link OperandType::TENSOR_FLOAT16}, the
+ * alpha value must be of {@link OperandType::FLOAT16}.
+ * For input tensor of {@link OperandType::TENSOR_FLOAT32}, the
+ * alpha value must be of {@link OperandType::FLOAT32}.
* * 4: A scalar, specifying the exponent, beta.
* For input tensor of {@link OperandType::TENSOR_FLOAT16}, the beta
* value must be of {@link OperandType::FLOAT16}.
@@ -1024,12 +1006,10 @@
* specifying the dimension normalization would be performed on.
* Negative index is used to specify axis from the end (e.g. -1 for
* the last axis). Must be in the range [-n, n).
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
*/
LOCAL_RESPONSE_NORMALIZATION = @1.1::OperationType:LOCAL_RESPONSE_NORMALIZATION,
@@ -1041,22 +1021,20 @@
* output = 1 / (1 + exp(-input))
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
* Supported tensor rank: up to 4.
*
* Inputs:
- * * 0: A tensor, specifying the input. Since API level 29, this tensor may
- * be zero-sized.
+ * * 0: A tensor, specifying the input.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 256 and the zeroPoint must be 0.
- *
- * Available since API level 27.
*/
LOGISTIC = @1.1::OperationType:LOGISTIC,
@@ -1064,7 +1042,7 @@
* Projects an input to a bit vector via locality senstive hashing.
*
* Supported input tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_INT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
@@ -1086,7 +1064,7 @@
* Tensor[1].Dim[0] == Tensor[2].Dim[0]
* * 3: Type:
* Sparse:
- * Value LSHProjectionType_SPARSE(=3) (since API level 29).
+ * Value LSHProjectionType_SPARSE(=3) (since HAL version 1.2).
* Computed bit vector is considered to be sparse.
* Each output element is an int32 made up of multiple bits
* computed from hash functions.
@@ -1107,14 +1085,12 @@
* Outputs:
* * 0: If the projection type is Sparse:
* Output.Dim == { Tensor[0].Dim[0] }
- * A tensor of int32 that represents hash signatures,
+ * A tensor of int32 that represents hash signatures.
*
* If the projection type is Dense:
* Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
* A flattened tensor that represents projected bit vectors.
- *
- * Available since API level 27.
- * The offset value for sparse projections was added in API level 29.
+ * The offset value for sparse projections was added in HAL version 1.2.
*/
LSH_PROJECTION = @1.1::OperationType:LSH_PROJECTION,
@@ -1170,7 +1146,7 @@
* matrix, each element of which is the product of the corresponding
* elements of the input matrices.
*
- * Since API level 29 LSTM supports layer normalization.
+ * Since HAL version 1.2 LSTM supports layer normalization.
* In case layer normalization is used, the inputs to internal activation
* functions (sigmoid and \f$g\f$) are normalized, rescaled and recentered
* following an approach from section 3.1 from
@@ -1197,7 +1173,7 @@
* * The projection bias (\f$b_{proj}\f$) may (but not required to) have a
* value if the recurrent projection layer exists, and should otherwise
* have no value.
- * * (API level >= 29) The four layer normalization weights either all have
+ * * (HAL version 1.2 or later) The four layer normalization weights either all have
* values or none of them have values. Additionally, if CIFG is used,
* input layer normalization weights tensor is omitted and the other layer
* normalization weights either all have values or none of them have
@@ -1228,7 +1204,7 @@
* Jimmy Ba et al. "Layer Normalization"
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* All input and output tensors must be of the same type.
@@ -1291,24 +1267,24 @@
* * 21:The clipping threshold (\f$t_{cell}\f$) for the cell state, such
* that values are bound within [-cell_clip, cell_clip]. If set to 0.0
* then clipping is disabled.
- * Until API level 29 this scalar must be of type {@link
- * FLOAT32}. Since API level 29, if all the input
+ * Until HAL version 1.2 this scalar must be of type {@link
+ * OperandType::FLOAT32}. Since HAL version 1.2, if all the input
* tensors have type {@link OperandType::TENSOR_FLOAT32}, this
* scalar must be of the type {@link OperandType::FLOAT32},
* otherwise if all the input tensors have the type {@link
- * TENSOR_FLOAT16}, this scalar must be of type {@link
- * FLOAT16}.
+ * OperandType::TENSOR_FLOAT16}, this scalar must be of type {@link
+ * OperandType::FLOAT16}.
* * 22:The clipping threshold (\f$t_{proj}\f$) for the output from the
* projection layer, such that values are bound within
* [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
- * Until API level 29 this scalar must be of type {@link
- * FLOAT32}. Since API level 29, if all the input
+ * Until HAL version 1.2 this scalar must be of type {@link
+ * OperandType::FLOAT32}. Since HAL version 1.2, if all the input
* tensors have type {@link OperandType::TENSOR_FLOAT32}, this
* scalar must be of the type {@link OperandType::FLOAT32},
* otherwise if all the input tensors have the type {@link
- * TENSOR_FLOAT16}, this scalar must be of type {@link
- * FLOAT16}.
- * Since API level 29 there are additional inputs to this op:
+ * OperandType::TENSOR_FLOAT16}, this scalar must be of type {@link
+ * OperandType::FLOAT16}.
+ * Since HAL version 1.2 there are additional inputs to this op:
* * 23:The input layer normalization weights.
* A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
* to activation at input gate.
@@ -1333,8 +1309,6 @@
* * 3: The output (\f$o_t\f$).
* A 2-D tensor of shape [batch_size, output_size]. This is effectively
* the same as the current “output state (out)” value.
- *
- * Available since API level 27.
*/
LSTM = @1.1::OperationType:LSTM,
@@ -1352,7 +1326,7 @@
* )
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -1360,13 +1334,14 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both explicit padding and implicit padding are supported.
*
* Inputs (explicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the padding on
* the left, in the ‘width’ dimension.
* * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -1388,12 +1363,12 @@
* invoke on the result.
* * 10: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Inputs (implicit padding):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the implicit
* padding scheme, has to be one of the
* following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -1410,13 +1385,13 @@
* invoke on the result.
* * 7: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
MAX_POOL_2D = @1.1::OperationType:MAX_POOL_2D,
@@ -1435,15 +1410,15 @@
* of the input operands. It starts with the trailing dimensions, and works
* its way forward.
*
- * Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
- * * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM}
- *
- * Since API level 29, generic zero-sized input tensor is supported. Zero
+ * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
* dimension is only compatible with 0 or 1. The size of the output
* dimension is zero if either of corresponding input dimension is zero.
*
+ * Supported tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
+ * * {@link OperandType::TENSOR_FLOAT32}
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ *
* Supported tensor rank: up to 4
*
* Inputs:
@@ -1459,8 +1434,6 @@
* For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
* the following condition must be satisfied:
* output_scale > input1_scale * input2_scale.
- *
- * Available since API level 27.
*/
MUL = @1.1::OperationType:MUL,
@@ -1472,20 +1445,20 @@
* output = max(0, input)
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
* Supported tensor rank: up to 4.
*
* Inputs:
- * * 0: A tensor, specifying the input. Since API level 29, this tensor may
- * be zero-sized.
+ * * 0: A tensor, specifying the input.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU = @1.1::OperationType:RELU,
@@ -1497,20 +1470,20 @@
* output = min(1.f, max(-1.f, input))
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
* Supported tensor rank: up to 4.
*
* Inputs:
- * * 0: A tensor, specifying the input. Since API level 29, this tensor may
- * be zero-sized.
+ * * 0: A tensor, specifying the input.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
- * * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * * 0: The output tensor of the same shape as input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU1 = @1.1::OperationType:RELU1,
@@ -1522,20 +1495,20 @@
* output = min(6, max(0, input))
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
* Supported tensor rank: up to 4.
*
* Inputs:
- * * 0: A tensor, specifying the input. Since API level 29, this tensor may
- * be zero-sized.
+ * * 0: A tensor, specifying the input.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RELU6 = @1.1::OperationType:RELU6,
@@ -1546,7 +1519,7 @@
* tensor, but with a newly specified shape.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -1565,8 +1538,8 @@
*
* Outputs:
* * 0: The output tensor, of shape specified by the input shape.
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RESHAPE = @1.1::OperationType:RESHAPE,
@@ -1578,30 +1551,31 @@
* same as corner pixels of input.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
*
* Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Both resizing by shape and resizing by scale are supported.
*
* Inputs (resizing by shape):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
- * the input. Since API level 29, zero batches is supported for this
- * tensor.
+ * the input.
+ * Since HAL version 1.2, zero batches is supported for this tensor.
* * 1: An {@link OperandType::INT32} scalar, specifying the output
* width of the output tensor.
* * 2: An {@link OperandType::INT32} scalar, specifying the output
* height of the output tensor.
* * 3: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
- * Inputs (resizing by scale, since API level 29):
+ * Inputs (resizing by scale, since HAL version 1.2):
* * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
* the input. Zero batches is supported for this tensor.
* * 1: A scalar, specifying width_scale, the scaling factor of the width
@@ -1622,8 +1596,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, new_height, new_width, depth].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RESIZE_BILINEAR = @1.1::OperationType:RESIZE_BILINEAR,
@@ -1644,7 +1618,7 @@
* argument (if not “NONE”).
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* The input tensors must all be the same type.
@@ -1676,8 +1650,6 @@
* * 1: output.
* A 2-D tensor of shape [batch_size, num_units]. This is effectively
* the same as the current state value.
- *
- * Available since API level 27.
*/
RNN = @1.1::OperationType:RNN,
@@ -1696,34 +1668,32 @@
* independently on each 1-D slice along specified dimension.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
* Supported tensor rank: up to 4.
- * Tensors with rank other than 2 or 4 are only supported since API level 29.
+ * Tensors with rank other than 2 or 4 are only supported since HAL version 1.2.
*
* Inputs:
- * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped. Since
- * API level 29, this tensor may be zero-sized.
+ * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
+ * Since HAL version 1.2, this tensor may be zero-sized.
* * 1: A scalar, specifying the positive scaling factor for the exponent,
* beta. If input0 is of {@link OperandType::TENSOR_FLOAT32} or
* {@link OperandType::TENSOR_QUANT8_ASYMM}, the scalar must be of
- * {@link OperandType::FLOAT32}. If input0 is of {@link
- * OperandType::TENSOR_FLOAT16}, then the scalar must be of {@link
- * OperandType::FLOAT16}.
+ * {@link OperandType::FLOAT32}.
+ * If input0 is of {@link OperandType::TENSOR_FLOAT16}, then the
+ * scalar must be of {@link OperandType::FLOAT16}.
* * 2: An optional {@link OperandType::INT32} scalar, default to -1,
* specifying the dimension the activation would be performed on.
* Negative index is used to specify axis from the end (e.g. -1 for
* the last axis). Must be in the range [-n, n).
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 256 and the zeroPoint must be 0.
- *
- * Available since API level 27.
*/
SOFTMAX = @1.1::OperationType:SOFTMAX,
@@ -1742,7 +1712,7 @@
* The input tensor's height and width must be divisible by block_size.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -1750,6 +1720,7 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Inputs:
* * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -1759,13 +1730,13 @@
* input height and width.
* * 2: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: The output 4-D tensor, of shape [batches, height/block_size,
* width/block_size, depth_in*block_size*block_size].
- *
- * Available since API level 27.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SPACE_TO_DEPTH = @1.1::OperationType:SPACE_TO_DEPTH,
@@ -1809,7 +1780,7 @@
* the filters.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* All input tensors must be the same type.
@@ -1843,8 +1814,6 @@
* * 1: output.
* A 2-D tensor of the same {@link OperandType} as the inputs, with shape
* [batch_size, num_units].
- *
- * Available since API level 27.
*/
SVDF = @1.1::OperationType:SVDF,
@@ -1856,22 +1825,20 @@
* output = tanh(input)
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
*
* Supported tensor rank: up to 4.
*
* Inputs:
- * * 0: A tensor, specifying the input. Since API level 29, this tensor may
- * be zero-sized.
+ * * 0: A tensor, specifying the input.
+ * Since HAL version 1.2, this tensor may be zero-sized.
*
* Outputs:
* * 0: The output tensor of same shape as input0.
* For {@link OperandType::TENSOR_QUANT8_ASYMM},
* the scale must be 1.f / 128 and the zeroPoint must be 128.
- *
- * Available since API level 27.
*/
TANH = @1.1::OperationType:TANH,
@@ -1886,7 +1853,7 @@
* This is the reverse of SpaceToBatch.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -1894,6 +1861,7 @@
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Inputs:
* * 0: An n-D tensor, specifying the tensor to be reshaped
@@ -1906,8 +1874,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
BATCH_TO_SPACE_ND = @1.1::OperationType:BATCH_TO_SPACE_ND,
@@ -1931,12 +1899,12 @@
* input2.dimension = {5, 4, 3, 1}
* output.dimension = {5, 4, 3, 2}
*
- * Since API level 29, generic zero-sized input tensor is supported. Zero
+ * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
* dimension is only compatible with 0 or 1. The size of the output
* dimension is zero if either of corresponding input dimension is zero.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
*
* Supported tensor rank: up to 4
@@ -1951,8 +1919,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
*/
DIV = @1.1::OperationType:DIV,
@@ -1965,7 +1931,7 @@
* length 1.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -1987,21 +1953,21 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be same as input0.
*/
MEAN = @1.1::OperationType:MEAN,
/**
- * Pads a tensor with zeros.
+ * Pads a tensor.
*
* This operation pads a tensor according to the specified paddings.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API
- * level 29, see the output section)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * (full support since HAL version 1.2, see the output section)
*
* Supported tensor rank: up to 4
*
@@ -2023,12 +1989,12 @@
* of the padding:
* output0.dimension[i] =
* padding[i, 0] + input0.dimension[i] + padding[i, 1]
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*
- * NOTE: Before API level 29, the pad value for
- * {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} is undefined.
- * Since API level 29, the pad value is always the logical zero.
- *
- * Available since API level 28.
+ * NOTE: Before HAL version 1.2, the pad value for
+ * {@link OperandType::TENSOR_QUANT8_ASYMM} is undefined.
+ * Since HAL version 1.2, the pad value is always the logical zero.
*/
PAD = @1.1::OperationType:PAD,
@@ -2044,14 +2010,16 @@
* dimensions of the input are optionally zero padded according to paddings.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
+ * (full support since HAL version 1.2, see the output section)
*
* Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
* With the default data layout NHWC, the data is stored in the order of:
* [batch, height, width, channels]. Alternatively, the data layout could
* be NCHW, the data storage order of: [batch, channels, height, width].
+ * NCHW is supported since HAL version 1.2.
*
* Inputs:
* * 0: An n-D tensor, specifying the input.
@@ -2068,12 +2036,16 @@
* end of dimension i.
* * 3: An optional {@link OperandType::BOOL} scalar, default to false.
* Set to true to specify NCHW data layout for input0 and output0.
- * Available since API level 29.
+ * Available since HAL version 1.2.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*
- * Available since API level 28.
+ * NOTE: Before HAL version 1.2, the pad value for
+ * {@link OperandType::TENSOR_QUANT8_ASYMM} is undefined.
+ * Since HAL version 1.2, the pad value is always the logical zero.
*/
SPACE_TO_BATCH_ND = @1.1::OperationType:SPACE_TO_BATCH_ND,
@@ -2086,7 +2058,7 @@
* dimensions by specifying the axes (input1).
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -2104,8 +2076,8 @@
* * 0: A tensor of the same {@link OperandType} as input0. Contains the
* same data as input, but has one or more dimensions of size 1
* removed.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SQUEEZE = @1.1::OperationType:SQUEEZE,
@@ -2119,7 +2091,7 @@
* reverse slice.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -2151,8 +2123,8 @@
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
* where k is the number of bits set in shrink_axis_mask.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
STRIDED_SLICE = @1.1::OperationType:STRIDED_SLICE,
@@ -2176,14 +2148,14 @@
* input2.dimension = {5, 4, 3, 1}
* output.dimension = {5, 4, 3, 2}
*
- * Since API level 29, generic zero-sized input tensor is supported. Zero
+ * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
* dimension is only compatible with 0 or 1. The size of the output
* dimension is zero if either of corresponding input dimension is zero.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
- * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
*
* Supported tensor rank: up to 4
*
@@ -2197,8 +2169,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
SUB = @1.1::OperationType:SUB,
@@ -2212,7 +2184,7 @@
* regular matrix transpose on 2-D input Tensors.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -2220,14 +2192,14 @@
*
* Inputs:
* * 0: An n-D tensor, specifying the tensor to be transposed.
- * Since API level 29, this tensor may be zero-sized.
+ * Since HAL version 1.2, this tensor may be zero-sized.
* * 1: An optional 1-D Tensor of {@link OperandType::TENSOR_INT32},
* the permutation of the dimensions of the input tensor.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 28.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
TRANSPOSE = @1.1::OperationType:TRANSPOSE,
@@ -2245,8 +2217,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
ABS = 38,
@@ -2269,8 +2239,6 @@
*
* Outputs:
* * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
- *
- * Available since API level 29.
*/
// There is no underscore in ARG_MAX to avoid name conflict with
// the macro defined in libc/kernel/uapi/linux/limits.h.
@@ -2295,8 +2263,6 @@
*
* Outputs:
* * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
- *
- * Available since API level 29.
*/
ARGMIN = 40, // See ARGMAX for naming discussion.
@@ -2341,8 +2307,8 @@
* * 0: A tensor of the same {@link OperandType} as input0, with shape
* [num_rois, num_classes * 4], specifying the coordinates of each
* output bounding box for each class, with format [x1, y1, x2, y2].
- *
- * Available since API level 29.
+ * For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the
+ * scale must be 0.125 and the zero point must be 0.
*/
AXIS_ALIGNED_BBOX_TRANSFORM = 41,
@@ -2482,17 +2448,15 @@
* then clipping is disabled.
* If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
* this scalar must be of the type {@link OperandType::FLOAT32},
- * otherwise if all the input tensors have the type {@link
- * TENSOR_FLOAT16}, this scalar must be of type {@link
- * FLOAT16}.
+ * otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
+ * this scalar must be of type {@link OperandType::FLOAT16}.
* * 50: The clipping threshold for the output from the
* projection layer, such that values are bound within
* [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
* If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
* this scalar must be of the type {@link OperandType::FLOAT32},
- * otherwise if all the input tensors have the type {@link
- * TENSOR_FLOAT16}, this scalar must be of type {@link
- * FLOAT16}.
+ * otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
+ * this scalar must be of type {@link OperandType::FLOAT16}.
* * 51: merge_outputs
* An {@link OperandType::BOOL} scalar specifying if the outputs
* from forward and backward cells should be merged.
@@ -2539,8 +2503,6 @@
* A 3-D tensor of shape:
* If time-major: [max_time, batch_size, bw_output_size]
* If batch-major: [batch_size, max_time, bw_output_size]
- *
- * Available since API level 29.
*/
BIDIRECTIONAL_SEQUENCE_LSTM = 42,
@@ -2658,8 +2620,6 @@
* (timeMajor). If it is set to true, then the shape is set to
* [maxTime, batchSize, bwNumUnits], otherwise the shape is set to
* [batchSize, maxTime, bwNumUnits].
- *
- * Available since API level 29.
*/
BIDIRECTIONAL_SEQUENCE_RNN = 43,
@@ -2737,8 +2697,6 @@
* * 3: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape
* [num_output_rois], specifying the batch index of each box. Boxes
* with the same batch index are grouped together.
- *
- * Available since API level 29.
*/
BOX_WITH_NMS_LIMIT = 44,
@@ -2762,8 +2720,6 @@
*
* Outputs:
* * 0: A tensor with the same shape as input0.
- *
- * Available since API level 29.
*/
CAST = 45,
@@ -2800,8 +2756,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} and same shape as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
CHANNEL_SHUFFLE = 46,
@@ -2856,14 +2812,14 @@
* * 11: A scalar, score_threshold. Boxes with scores lower than the
* threshold are filtered before sending to the NMS algorithm. The
* scalar must be of {@link OperandType::FLOAT16} if input0 is of
- * {@link OperandType::TENSOR_FLOAT16} and of {@link
- * OperandType::FLOAT32} if input0 is of {@link
- * OperandType::TENSOR_FLOAT32}.
+ * {@link OperandType::TENSOR_FLOAT16} and of
+ * {@link OperandType::FLOAT32} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT32}.
* * 12: A scalar, specifying the IoU threshold for hard NMS. The scalar
- * must be of {@link OperandType::FLOAT16} if input0 is of {@link
- * OperandType::TENSOR_FLOAT16} and of {@link
- * OperandType::FLOAT32} if input0 is of {@link
- * OperandType::TENSOR_FLOAT32}.
+ * must be of {@link OperandType::FLOAT16} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT16} and of
+ * {@link OperandType::FLOAT32} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT32}.
* * 13: An {@link OperandType::BOOL} scalar, set to true to include
* background class in the list of label map for the output, set
* to false to not include the background. When the background
@@ -2882,8 +2838,6 @@
* output detection.
* * 3: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape [batches],
* specifying the number of valid output detections for each batch.
- *
- * Available since API level 29.
*/
DETECTION_POSTPROCESSING = 47,
@@ -2908,8 +2862,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
EQUAL = 48,
@@ -2927,8 +2879,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
EXP = 49,
@@ -2956,8 +2906,8 @@
* Outputs:
* * 0: An (n + 1)-D tensor with the same {@link OperandType} and data as
* input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
EXPAND_DIMS = 50,
@@ -2994,8 +2944,8 @@
*
* Outputs:
* * 0: An (n + k - 1)-D tensor with the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
GATHER = 51,
@@ -3074,8 +3024,6 @@
* * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape
* [num_output_rois], specifying the batch index of each box. Boxes
* with the same batch index are grouped together.
- *
- * Available since API level 29.
*/
GENERATE_PROPOSALS = 52,
@@ -3100,8 +3048,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
GREATER = 53,
/**
@@ -3125,8 +3071,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
GREATER_EQUAL = 54,
@@ -3191,7 +3135,8 @@
* [depth_out, filter_height, filter_width, depth_group], specifying
* the filter, where depth_out must be divisible by num_groups. For
* tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * the channel dimension must be set to 0.
+ * the channel dimension (channelDim at
+ * {@link SymmPerChannelQuantParams}) must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
* tensor of type {@link OperandType::TENSOR_FLOAT32} or
* {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
@@ -3229,7 +3174,8 @@
* [depth_out, filter_height, filter_width, depth_group], specifying
* the filter, where depth_out must be divisible by num_groups. For
* tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
- * the channel dimension must be set to 0.
+ * the channel dimension (SymmPerChannelQuantParams::channelDim)
+ * must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
* tensor of type {@link OperandType::TENSOR_FLOAT32} or
* {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
@@ -3258,8 +3204,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth_out].
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
GROUPED_CONV_2D = 55,
@@ -3300,12 +3246,14 @@
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0, with shape
* [num_boxes, num_keypoints], specifying score of the keypoints.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from input0 scale and zeroPoint.
* * 1: A tensor of the same {@link OperandType} as input1, with shape
* [num_boxes, num_keypoints, 2], specifying the location of
* the keypoints, the second dimension is organized as
* [keypoint_x, keypoint_y].
- *
- * Available since API level 29.
+ * For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the
+ * scale must be 0.125 and the zero point must be 0.
*/
HEATMAP_MAX_KEYPOINT = 56,
@@ -3339,26 +3287,24 @@
* * 0: An n-D tensor, specifying the tensor to be normalized.
* * 1: A scalar, specifying gamma, the scale applied to the normalized
* tensor. The scalar must be of {@link OperandType::FLOAT16} if
- * input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
- * OperandType::FLOAT32} if input0 is of {@link
- * OperandType::TENSOR_FLOAT32}.
+ * input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+ * {@link OperandType::FLOAT32} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT32}.
* * 2: A scalar, specifying beta, the offset applied to the normalized
* tensor. The scalar must be of {@link OperandType::FLOAT16} if
- * input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
- * OperandType::FLOAT32} if input0 is of {@link
- * OperandType::TENSOR_FLOAT32}.
+ * input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+ * {@link OperandType::FLOAT32} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT32}.
* * 3: A scalar, specifying epsilon, the small value added to variance to
* avoid dividing by zero. The scalar must be of {@link OperandType::FLOAT16} if
- * input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
- * OperandType::FLOAT32} if input0 is of {@link
- * OperandType::TENSOR_FLOAT32}.
+ * input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+ * {@link OperandType::FLOAT32} if input0 is of
+ * {@link OperandType::TENSOR_FLOAT32}.
* * 4: An {@link OperandType::BOOL} scalar, set to true to specify
* NCHW data layout for input0 and output0. Set to false for NHWC.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} and same shape as input0.
- *
- * Available since API level 29.
*/
INSTANCE_NORMALIZATION = 57,
@@ -3383,8 +3329,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
LESS = 58,
@@ -3409,8 +3353,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
LESS_EQUAL = 59,
@@ -3428,8 +3370,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
LOG = 60,
@@ -3450,8 +3390,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
LOGICAL_AND = 61,
@@ -3468,8 +3406,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
LOGICAL_NOT = 62,
@@ -3490,8 +3426,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
LOGICAL_OR = 63,
@@ -3523,8 +3457,6 @@
* Outputs:
* * 0: The output tensor of the same {@link OperandType} and shape as
* input0.
- *
- * Available since API level 29.
*/
LOG_SOFTMAX = 64,
@@ -3543,11 +3475,13 @@
* * 0: A tensor.
* * 1: A tensor of the same {@link OperandType} and compatible dimensions
* with input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scales and zeroPoint can be different from input0 scale and zeroPoint.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
MAXIMUM = 65,
@@ -3566,11 +3500,13 @@
* * 0: A tensor.
* * 1: A tensor of the same {@link OperandType} and compatible dimensions
* with input0.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scales and zeroPoint can be different from input0 scale and zeroPoint.
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
MINIMUM = 66,
@@ -3589,8 +3525,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
NEG = 67,
@@ -3615,8 +3549,6 @@
*
* Outputs:
* * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
- *
- * Available since API level 29.
*/
NOT_EQUAL = 68,
@@ -3657,8 +3589,8 @@
* of the padding:
* output0.dimension[i] =
* padding[i, 0] + input0.dimension[i] + padding[i, 1]
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
PAD_V2 = 69,
@@ -3689,8 +3621,6 @@
*
* Outputs:
* * 0: An output tensor.
- *
- * Available since API level 29.
*/
POW = 70,
@@ -3728,8 +3658,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be diffent from the input0 scale and zeroPoint.
*/
PRELU = 71,
@@ -3752,8 +3682,6 @@
* Outputs:
* * 0: The output tensor of same shape as input0, but with
* {@link OperandType::TENSOR_QUANT8_ASYMM}.
- *
- * Available since API level 29.
*/
QUANTIZE = 72,
@@ -3879,8 +3807,6 @@
* Outputs:
* * 0: A 2-D {@link OperandType::TENSOR_INT32} tensor with shape
* [batches, samples], containing the drawn samples.
- *
- * Available since API level 29.
*/
RANDOM_MULTINOMIAL = 74,
@@ -3906,8 +3832,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
*/
REDUCE_ALL = 75,
@@ -3933,8 +3857,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
*/
REDUCE_ANY = 76,
@@ -3962,8 +3884,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
REDUCE_MAX = 77,
@@ -3991,8 +3913,8 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
REDUCE_MIN = 78,
@@ -4018,8 +3940,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
*/
REDUCE_PROD = 79,
@@ -4045,8 +3965,6 @@
*
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0.
- *
- * Available since API level 29.
*/
REDUCE_SUM = 80,
@@ -4064,7 +3982,7 @@
* interpolation.
*
* Supported tensor {@link OperandType}:
- * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+ * * {@link OperandType::TENSOR_FLOAT16}
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
*
@@ -4105,8 +4023,8 @@
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0. The output
* shape is [num_rois, out_height, out_width, depth].
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from the input0 scale and zeroPoint.
*/
ROI_ALIGN = 81,
@@ -4156,8 +4074,8 @@
* Outputs:
* * 0: A tensor of the same {@link OperandType} as input0. The output
* shape is [num_rois, out_height, out_width, depth].
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
ROI_POOLING = 82,
@@ -4175,8 +4093,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
RSQRT = 83,
@@ -4201,9 +4117,13 @@
* true) or input2 (if false).
* * 1: An input tensor of the same shape as input0.
* * 2: An input tensor of the same shape and type as input1.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scales and zeroPoint can be different from input1 scale and zeroPoint.
*
* Outputs:
* * 0: A tensor of the same type and shape as input1 and input2.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*
*/
SELECT = 84,
@@ -4222,8 +4142,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
SIN = 85,
@@ -4235,7 +4153,6 @@
* for each dimension. The size is specified as a 1-D tensor containing
* either size of a slice along corresponding dimension or -1. In the latter
* case, all the remaining elements in dimension are included in the slice.
- * Slice size in each dimension cannot be zero.
*
* A sum of begin offset and a size of a slice must not exceed size of a
* corresponding dimension.
@@ -4257,8 +4174,8 @@
*
* Outputs:
* * 0: An n-D tensor of the same type as the input containing the slice.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * its scale and zeroPoint has to be same as the input0 scale and zeroPoint.
*/
SLICE = 86,
@@ -4282,8 +4199,8 @@
*
* Outputs:
* * 0 ~ (num_splits - 1): Resulting subtensors.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
SPLIT = 87,
@@ -4301,8 +4218,6 @@
*
* Outputs:
* * 0: The output tensor of same shape as input0.
- *
- * Available since API level 29.
*/
SQRT = 88,
@@ -4330,8 +4245,8 @@
*
* Outputs:
* * 0: A tiled tensor of the same {@link OperandType} and rank as `input`.
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
TILE = 89,
@@ -4357,10 +4272,10 @@
* Outputs:
* * 0: An n-D tensor of the same type as the input, containing the k
* largest elements along each last dimensional slice.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
* * 1: An n-D tensor of type {@link OperandType::TENSOR_INT32}
* containing the indices of values within the last dimension of input.
- *
- * Available since API level 29.
*/
TOPK_V2 = 90,
@@ -4374,7 +4289,7 @@
* The output dimensions are functions of the filter dimensions, stride, and
* padding.
*
- * Supported tensor {@link OperandCode} configurations:
+ * Supported tensor {@link OperandType} configurations:
* * 16 bit floating point:
* * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
*
@@ -4406,7 +4321,7 @@
* [depth_out, filter_height, filter_width, depth_in], specifying the
* filter. For tensor of type
* {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
- * dimension (extraParams.channelQuant.channelDim) must be set to 0.
+ * dimension (SymmPerChannelQuantParams::channelDim) must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
* tensor of type {@link OperandType::TENSOR_FLOAT32} or
* {@link OperandType::TENSOR_FLOAT16}, the bias should be of the
@@ -4443,7 +4358,7 @@
* [depth_out, filter_height, filter_width, depth_in], specifying the
* filter. For tensor of type
* {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
- * dimension (extraParams.channelQuant.channelDim) must be set to 0.
+ * dimension (SymmPerChannelQuantParams::channelDim) must be set to 0.
* * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
* tensor of type {@link OperandType::TENSOR_FLOAT32} or
* {@link OperandType::TENSOR_FLOAT16}, the bias should be of the
@@ -4473,8 +4388,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, out_height, out_width, depth_out].
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint can be different from inputs' scale and zeroPoint.
*/
TRANSPOSE_CONV_2D = 91,
@@ -4584,8 +4499,6 @@
* A 3-D tensor of shape:
* If time-major: [max_time, batch_size, output_size]
* If batch-major: [batch_size, max_time, output_size]
- *
- * Available since API level 29.
*/
UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
@@ -4641,8 +4554,6 @@
* it is set to 1, then the output has a shape [maxTime, batchSize,
* numUnits], otherwise the output has a shape [batchSize, maxTime,
* numUnits].
- *
- * Available since API level 29.
*/
UNIDIRECTIONAL_SEQUENCE_RNN = 93,
@@ -4696,8 +4607,8 @@
* Outputs:
* * 0: The output 4-D tensor, of shape
* [batches, new_height, new_width, depth].
- *
- * Available since API level 29.
+ * For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+ * the scale and zeroPoint must be the same as input0.
*/
RESIZE_NEAREST_NEIGHBOR = 94,
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
new file mode 100644
index 0000000..cab330d
--- /dev/null
+++ b/neuralnetworks/1.2/types.t
@@ -0,0 +1,745 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * Copyright (C) 2018 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.neuralnetworks@1.2;
+
+import @1.0::DataLocation;
+import @1.0::ErrorStatus;
+import @1.0::OperandLifeTime;
+import @1.0::OperandType;
+import @1.0::PerformanceInfo;
+import @1.1::OperationType;
+
+import android.hidl.safe_union@1.0::Monostate;
+
+enum Constant : uint32_t {
+ /**
+ * The byte size of the cache token.
+ */
+ BYTE_SIZE_OF_CACHE_TOKEN = 32,
+
+ /**
+ * The maximum number of files for each type of cache in compilation caching.
+ */
+ MAX_NUMBER_OF_CACHE_FILES = 32,
+};
+
+enum OperandType : @1.0::OperandType {
+%insert Operand_1.2
+
+ /*
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
+ *
+ * OEM specific scalar value.
+ * OEM = 10000,
+ */
+ /*
+ * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+ * alternative to OEM operation and data types.
+ *
+ * A tensor of OEM specific values.
+ * TENSOR_OEM_BYTE = 10001,
+ */
+ /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF
+ * OperandTypeRange::FUNDAMENTAL_MAX.
+ */
+ /* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF
+ * OperandTypeRange::OEM_MAX.
+ */
+};
+
+/**
+ * The range of operand values in the OperandType enum.
+ */
+enum OperandTypeRange : uint32_t {
+ BASE_MIN = 0,
+ FUNDAMENTAL_MIN = 0,
+%insert Operand_1.2_MAX
+ OEM_MIN = 10000,
+ OEM_MAX = 10001,
+ BASE_MAX = 0xFFFF,
+};
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : int32_t {
+
+%insert Operation_1.0
+
+%insert Operation_1.1
+
+%insert Operation_1.2
+
+ /**
+ * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+ * OEM operation and data types.
+ *
+ * This operation is OEM specific. It should only be used for OEM
+ * applications.
+ */
+ OEM_OPERATION = @1.1::OperationType:OEM_OPERATION,
+ /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
+ * OperationTypeRange::FUNDAMENTAL_MAX.
+ */
+ /* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF
+ * OperationTypeRange::OEM_MAX.
+ */
+};
+
+/**
+ * The range of values in the OperationType enum.
+ */
+enum OperationTypeRange : uint32_t {
+ BASE_MIN = 0,
+ FUNDAMENTAL_MIN = 0,
+%insert Operation_1.2_MAX
+ OEM_MIN = 10000,
+ OEM_MAX = 10000,
+ BASE_MAX = 0xFFFF,
+};
+
+/**
+ * Device types.
+ *
+ * The type of NNAPI device.
+ */
+enum DeviceType : int32_t {
+ // Leaving 0 unused as it means unknown type in NDK NNAPI. There is no
+ // HAL equivalent of unknown type and a 1.2 HAL implementation must belong
+ // to one of the categories below.
+ /** The device does not fall into any category below. */
+ OTHER = 1,
+ /** The device runs NNAPI models on single or multi-core CPU. */
+ CPU = 2,
+ /** The device can run NNAPI models and also accelerate graphics APIs such
+ * as OpenGL ES and Vulkan. */
+ GPU = 3,
+ /** Dedicated accelerator for Machine Learning workloads. */
+ ACCELERATOR = 4,
+};
+
+/**
+ * The capabilities of a driver.
+ *
+ * Performance of an operation comes from the type of its first operand.
+ * This represents performance for non extension operand types.
+ */
+struct Capabilities {
+ /**
+ * Driver performance when operating on float32 data but performing
+ * calculations with range and/or precision as low as that of the IEEE
+ * 754 16-bit floating-point format.
+ */
+ PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
+ PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+
+ /**
+ * Driver performance when operating on a particular data type.
+ * In the case of float32 data, this is used when the calculations
+ * are not relaxed.
+ */
+ struct OperandPerformance {
+ OperandType type;
+ PerformanceInfo info;
+ };
+
+ /**
+ * Performance by operand type. Must be sorted by OperandType.
+ * If a particular OperandType is not present in operandPerformance,
+ * its performance is treated as { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
+ */
+ vec<OperandPerformance> operandPerformance;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+ /**
+ * The operation type.
+ *
+ * Besides the values listed in {@link OperationType}, any value above
+ * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
+ * as an extension type according to {@link Model::extensionNameToPrefix}.
+ */
+ OperationType type;
+
+ /**
+ * Describes the table that contains the indexes of the inputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> inputs;
+
+ /**
+ * Describes the table that contains the indexes of the outputs of the
+ * operation. The offset is the index in the operandIndexes table.
+ */
+ vec<uint32_t> outputs;
+};
+
+/**
+ * Parameters for TENSOR_QUANT8_SYMM_PER_CHANNEL operand.
+ */
+struct SymmPerChannelQuantParams {
+ /** Array of scaling values for each channel. Each value must be greater than zero. */
+ vec<float> scales;
+ /** Index of the channel dimension */
+ uint32_t channelDim;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+ /**
+ * The data type.
+ *
+ * Besides the values listed in {@link OperandType}, any value above
+ * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
+ * as an extension type according to {@link Model::extensionNameToPrefix}.
+ */
+ OperandType type;
+
+ /**
+ * Dimensions of the operand.
+ *
+ * For a scalar operand, dimensions.size() must be 0.
+ *
+ * A tensor operand with all dimensions specified has "fully
+ * specified" dimensions. Whenever possible (i.e., whenever the
+ * dimensions are known at model construction time), a tensor
+ * operand should have (but is not required to have) fully
+ * specified dimensions, in order to enable the best possible
+ * performance.
+ *
+ * If a tensor operand's dimensions are not fully specified, the
+ * dimensions of the operand are deduced from the operand
+ * dimensions and values of the operation for which that operand
+ * is an output.
+ *
+ * In the following situations, a tensor operand's dimensions must
+ * be fully specified:
+ *
+ * . The operand has lifetime CONSTANT_COPY or
+ * CONSTANT_REFERENCE.
+ *
+ * . The operand has lifetime MODEL_INPUT. Fully
+ * specified dimensions must either be present in the
+ * Operand or they must be provided in the corresponding
+ * RequestArgument.
+ * EXCEPTION: If the input is optional and omitted
+ * (by setting the hasNoValue field of the corresponding
+ * RequestArgument to true) then it need not have fully
+ * specified dimensions.
+ *
+ * A tensor operand with some number of unspecified dimensions is
+ * represented by setting each unspecified dimension to 0.
+ *
+ * A tensor operand with unspecified rank is represented by providing
+ * an empty dimensions vector.
+ */
+ vec<uint32_t> dimensions;
+
+ /**
+ * The number of times this operand appears as an operation input.
+ *
+ * (For example, if this operand appears once in one operation's
+ * input list, and three times in another operation's input list,
+ * then numberOfConsumers = 4.)
+ */
+ uint32_t numberOfConsumers;
+
+ /**
+ * Quantized scale of the operand.
+ *
+ * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+ * TENSOR_INT32.
+ */
+ float scale;
+
+ /**
+ * Quantized zero-point offset of the operand.
+ *
+ * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+ */
+ int32_t zeroPoint;
+
+ /**
+ * How the operand is used.
+ */
+ OperandLifeTime lifetime;
+
+ /**
+ * Where to find the data for this operand.
+ * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+ * NO_VALUE:
+ * - All the fields must be 0.
+ * If the lifetime is CONSTANT_COPY:
+ * - location.poolIndex is 0.
+ * - location.offset is the offset in bytes into Model.operandValues.
+ * - location.length is set.
+ * If the lifetime is CONSTANT_REFERENCE:
+ * - location.poolIndex is set.
+ * - location.offset is the offset in bytes into the specified pool.
+ * - location.length is set.
+ */
+ DataLocation location;
+
+ /**
+ * Additional parameters specific to a particular operand type.
+ */
+ safe_union ExtraParams {
+ /**
+ * No additional parameters.
+ */
+ Monostate none;
+
+ /**
+ * Symmetric per-channel quantization parameters.
+ *
+ * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
+ */
+ SymmPerChannelQuantParams channelQuant;
+
+ /**
+ * Extension operand parameters.
+ *
+ * The framework treats this as an opaque data blob.
+ * The format is up to individual extensions.
+ */
+ vec<uint8_t> extension;
+ } extraParams;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+ /**
+ * All operands included in the model.
+ */
+ vec<Operand> operands;
+
+ /**
+ * All operations included in the model.
+ *
+ * The operations are sorted into execution order. Every operand
+ * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+ * written before it is read.
+ */
+ vec<Operation> operations;
+
+ /**
+ * Input indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> inputIndexes;
+
+ /**
+ * Output indexes of the model. There must be at least one.
+ *
+ * Each value corresponds to the index of the operand in "operands".
+ */
+ vec<uint32_t> outputIndexes;
+
+ /**
+ * A byte buffer containing operand data that were copied into the model.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_COPY.
+ */
+ vec<uint8_t> operandValues;
+
+ /**
+ * A collection of shared memory pools containing operand values.
+ *
+ * An operand's value must be located here if and only if Operand::lifetime
+ * equals OperandLifeTime::CONSTANT_REFERENCE.
+ */
+ vec<memory> pools;
+
+ /**
+ * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
+ * precision as low as that of the IEEE 754 16-bit floating-point format.
+ * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
+ * range and precision of the IEEE 754 32-bit floating-point format.
+ */
+ bool relaxComputationFloat32toFloat16;
+
+ /**
+ * The mapping between extension names and prefixes of operand and
+ * operation type values.
+ *
+ * An operand or operation whose numeric type value is above
+ * {@link OperandTypeRange::BASE_MAX} or
+ * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
+ * as an extension operand. The low
+ * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
+ * correspond to the type ID within the extension and the high
+ * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+ * the "prefix", which maps uniquely to the extension name.
+ *
+ * For example, if a model contains an operation whose value is
+ * 0xAAAABBBB and extensionNameToPrefix contains an entry with
+ * prefix=0xAAAA and name="vendor.test.test_extension", then
+ * the operation should be interpreted as the operation 0xBBBB
+ * of the extension named vendor.test.test_extension.
+ *
+ * This is a one-to-one correspondence. That is, there must be at most one
+ * prefix corresponding to each extension name and at most one extension
+ * name corresponding to each prefix.
+ */
+ vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+
+ /**
+ * A correspondence between an extension name and a prefix of operand and
+ * operation type values.
+ */
+ struct ExtensionNameAndPrefix {
+ /**
+ * The extension name.
+ *
+ * See {@link Extension::name} for the format specification.
+ */
+ string name;
+
+ /**
+ * The unique extension identifier within the model.
+ *
+ * See {@link Model::extensionNameToPrefix}.
+ */
+ uint16_t prefix;
+ };
+
+ /**
+ * Numeric values of extension operand and operation types have the
+ * following structure:
+ * - 16 high bits represent the "prefix", which corresponds uniquely to the
+ * extension name.
+ * - 16 low bits represent the type ID within the extension.
+ */
+ enum ExtensionTypeEncoding : uint8_t {
+ HIGH_BITS_PREFIX = 16,
+ LOW_BITS_TYPE = 16,
+ };
+};
+
+/**
+ * Describes the shape information of an output operand after execution.
+ */
+struct OutputShape {
+ /**
+ * Dimensions of the operand.
+ */
+ vec<uint32_t> dimensions;
+
+ /**
+ * Whether the provided buffer size is sufficient for the output.
+ */
+ bool isSufficient;
+};
+
+/**
+ * Specifies whether or not to measure timing information during execution.
+ */
+enum MeasureTiming : int32_t {
+ NO = 0,
+ YES = 1,
+};
+
+/**
+
+ * Timing information measured during execution. Each time is a duration from
+ * the beginning of some task to the end of that task, including time when that
+ * task is not active (for example, preempted by some other task, or
+ * waiting for some resource to become available).
+ *
+ * Times are measured in microseconds.
+ * When a time is not available, it must be reported as UINT64_MAX.
+ */
+struct Timing {
+ /** Execution time on device (not driver, which runs on host processor). */
+ uint64_t timeOnDevice;
+ /** Execution time in driver (including time on device). */
+ uint64_t timeInDriver;
+};
+
+/**
+ * FmqRequestDatum is a single element of a serialized representation of an
+ * execution request (a {@link @1.0::Request} object and a {@link MeasureTiming}
+ * value) which is sent across FastMessageQueue.
+ *
+ * The serialized representation for a particular execution is referred to later
+ * in these descriptions as a 'packet'.
+ *
+ * FastMessageQueue can only pass HIDL-defined types that do not involve nested
+ * buffers, handles, or interfaces.
+ *
+ * The request is serialized as follows:
+ * 1) 'packetInformation'
+ * 2) For each input operand:
+ * 2.1) 'inputOperandInformation'
+ * 2.2) For each dimension element of the operand:
+ * 2.2.1) 'inputOperandDimensionValue'
+ * 3) For each output operand:
+ * 3.1) 'outputOperandInformation'
+ * 3.2) For each dimension element of the operand:
+ * 3.2.1) 'outputOperandDimensionValue'
+ * 4) For each pool:
+ * 4.1) 'poolIdentifier'
+ * 5) 'measureTiming'
+ */
+safe_union FmqRequestDatum {
+ /**
+ * Type to describe the high-level layout of the packet.
+ */
+ struct PacketInformation {
+ /**
+ * How many elements the packet contains, including the
+ * "packetInformation" datum.
+ */
+ uint32_t packetSize;
+
+ /**
+ * Number of input operands.
+ */
+ uint32_t numberOfInputOperands;
+
+ /**
+ * Number of output operands.
+ */
+ uint32_t numberOfOutputOperands;
+
+ /**
+ * Number of pool identifiers.
+ */
+ uint32_t numberOfPools;
+ };
+
+ /**
+ * Type representing the information for each operand.
+ */
+ struct OperandInformation {
+ /**
+ * If true, the argument does not have a value. This can be used for
+ * operations that take optional arguments. If true, the fields of
+ * 'location' are set to 0, 'numberOfDimensions' is set to 0, and the
+ * dimensions information is omitted from the serialization.
+ */
+ bool hasNoValue;
+
+ /**
+ * The location within one of the memory pools passed in the Request.
+ */
+ DataLocation location;
+
+ /**
+ * Number of subsequent elements that belong to the dimensions vector.
+ */
+ uint32_t numberOfDimensions;
+ };
+
+ /**
+ * packetInformation is the first element of the packet and describes the
+ * remainder of the packet.
+ */
+ PacketInformation packetInformation;
+
+ /**
+ * Information for each input operand.
+ */
+ OperandInformation inputOperandInformation;
+
+ /**
+ * Element of the dimensions vector.
+ */
+ uint32_t inputOperandDimensionValue;
+
+ /**
+ * Information for each output operand.
+ */
+ OperandInformation outputOperandInformation;
+
+ /**
+ * Element of the dimensions vector.
+ */
+ uint32_t outputOperandDimensionValue;
+
+ /**
+ * Unique identifier for a pool.
+ *
+ * A {@link @1.0::Request} passes across one or more pools of shared memory
+ * for the inputs and outputs of an execution. However, these memory pools
+ * are not able to be sent across FastMessageQueue directly. Instead, the
+ * producing side of the FMQ represents each different pool with a unique
+ * identifier, and sends this identifier across the FMQ. Whenever the
+ * consuming side of the FMQ needs the memory corresponding to this unique
+ * identifier, it can pass the identifier to
+ * {@link IBurstCallback::getMemories} to retreive the memory. Although this
+ * HIDL Binder call is expensive compared to communication across FMQ, it is
+ * only needed in the cases when the consumer does not recognize the unique
+ * identifier.
+ */
+ int32_t poolIdentifier;
+
+ /**
+ * Specifies whether or not to measure duration of the execution. The
+ * duration runs from the time the driver dequeues the request from a
+ * FastMessageQueue to the time the driver enqueues results to a
+ * FastMessageQueue.
+ */
+ MeasureTiming measureTiming;
+};
+
+/**
+ * FmqResultDatum is a single element of a serialized representation of the
+ * values returned from an execution ({@link @1.0::ErrorStatus},
+ * vec<{@link OutputShape}>, and {@link Timing}) which is returned via
+ * FastMessageQueue.
+ *
+ * The serialized representation for a particular execution is referred to later
+ * in these descriptions as a 'packet'.
+ *
+ * FastMessageQueue can only pass HIDL-defined types that do not involve nested
+ * buffers, handles, or interfaces.
+ *
+ * The execution return values ({@link @1.0::ErrorStatus} and
+ * vec<{@link OutputShape}>) are serialized as follows:
+ * 1) 'packetInformation'
+ * 2) For each returned operand:
+ * 2.1) 'operandInformation'
+ * 2.2) For each dimension element of the operand:
+ * 2.2.1) 'operandDimensionValue'
+ * 3) 'executionTiming'
+ */
+safe_union FmqResultDatum {
+ /**
+ * Type to describe the high-level layout of the packet.
+ */
+ struct PacketInformation {
+ /**
+ * How many elements the packet contains, including the
+ * "packetInformation" datum.
+ */
+ uint32_t packetSize;
+
+ /**
+ * Status of the execution.
+ */
+ ErrorStatus errorStatus;
+
+ /**
+ * Number of returned operands.
+ */
+ uint32_t numberOfOperands;
+ };
+
+ /**
+ * Type representing the information for each operand.
+ */
+ struct OperandInformation {
+ /**
+ * Indicates whether the operand's output buffer is large enough to
+ * store the operand's result data.
+ */
+ bool isSufficient;
+
+ /**
+ * Number of subsequent elements that belong to the dimensions vector.
+ */
+ uint32_t numberOfDimensions;
+ };
+
+ /**
+ * packetInformation is the first element of the packet and describes the
+ * remainder of the packet. It additionally includes the status of the
+ * execution.
+ */
+ PacketInformation packetInformation;
+
+ /**
+ * Information for each returned operand.
+ */
+ OperandInformation operandInformation;
+
+ /**
+ * Element of the dimensions vector.
+ */
+ uint32_t operandDimensionValue;
+
+ /**
+ * Duration of execution. Unless measurement was requested and execution
+ * succeeds, all times must be reported as UINT64_MAX. A driver may choose
+ * to report any time as UINT64_MAX, indicating that measurement is not
+ * available.
+ */
+ Timing executionTiming;
+};
+
+/**
+ * Information about an extension.
+ */
+struct Extension {
+ /**
+ * The extension name.
+ *
+ * The name must consist of lowercase latin letters, numbers, periods, and
+ * underscore signs. The name must contain at least one period.
+ *
+ * The name must start with the reverse domain name of the vendor.
+ *
+ * Example: com.google.test_extension
+ */
+ string name;
+
+ /**
+ * Information about an extension operand type.
+ */
+ struct OperandTypeInformation {
+ /**
+ * The extension operand type.
+ */
+ uint16_t type;
+
+ /**
+ * Indicates whether the extension operand type represents a tensor or
+ * a scalar.
+ */
+ bool isTensor;
+
+ /**
+ * The byte size of the operand (if scalar) or of a single element (if
+ * tensor).
+ */
+ uint32_t byteSize;
+ };
+
+ /**
+ * Information about operand types defined by the extension.
+ */
+ vec<OperandTypeInformation> operandTypes;
+};
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
index 78766f2..68275ce 100644
--- a/power/stats/1.0/default/PowerStats.cpp
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -87,7 +87,7 @@
std::string railFileName;
std::string spsFileName;
uint32_t index = 0;
- uint32_t samplingRate;
+ unsigned long samplingRate;
for (const auto& path : mPm.devicePaths) {
railFileName = path + "/enabled_rails";
spsFileName = path + "/sampling_rate";
@@ -109,10 +109,11 @@
while (std::getline(railNames, line)) {
std::vector<std::string> words = android::base::Split(line, ":");
if (words.size() == 2) {
- mPm.railsInfo.emplace(words[0], RailData{.devicePath = path,
- .index = index,
- .subsysName = words[1],
- .samplingRate = samplingRate});
+ mPm.railsInfo.emplace(
+ words[0], RailData{.devicePath = path,
+ .index = index,
+ .subsysName = words[1],
+ .samplingRate = static_cast<uint32_t>(samplingRate)});
index++;
} else {
ALOGW("Unexpected format in file: %s", railFileName.c_str());
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index dffebd3..f10d753 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -161,7 +161,8 @@
ScanType type;
/**
- * Time interval in seconds between periodic scans, only valid when type = PERIODIC
+ * Time interval in seconds between the completion of one scan and the start of a subsequent scan.
+ * This field is only valid when 'type' is 'PERIODIC'.
* Range: ScanIntervalRange:MIN to ScanIntervalRange:MAX
*/
int32_t interval;
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index 5184ef9..a98f22a 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -46,7 +46,10 @@
::android::hardware::radio::V1_2::NetworkScanRequest request = {
.type = ScanType::ONE_SHOT,
.interval = 60,
- .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}};
+ .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
ASSERT_OK(res);
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index b2d19a2..d3012bb 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -178,7 +178,12 @@
.channels = {1, 2}};
::android::hardware::radio::V1_2::NetworkScanRequest request = {
- .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}};
+ .type = ScanType::ONE_SHOT,
+ .interval = 60,
+ .specifiers = {specifier},
+ .maxSearchTime = 60,
+ .incrementalResults = false,
+ .incrementalResultsPeriodicity = 1};
Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
ASSERT_OK(res);
diff --git a/tv/tuner/1.0/IDemux.hal b/tv/tuner/1.0/IDemux.hal
index e03095b..7ead34b 100644
--- a/tv/tuner/1.0/IDemux.hal
+++ b/tv/tuner/1.0/IDemux.hal
@@ -1,3 +1,19 @@
+/*
+ * 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 IDemuxCallback;
@@ -236,7 +252,7 @@
* INVALID_STATE if failed for wrong state.
* UNKNOWN_ERROR if failed for other reasons.
*/
- attachOutputTsFilter(DemuxFilterId filterId) generates (Result result);
+ attachOutputFilter(DemuxFilterId filterId) generates (Result result);
/**
* Detach one filter from the demux's output.
@@ -250,7 +266,7 @@
* INVALID_STATE if failed for wrong state.
* UNKNOWN_ERROR if failed for other reasons.
*/
- detachOutputTsFilter(DemuxFilterId filterId) generates (Result result);
+ detachOutputFilter(DemuxFilterId filterId) generates (Result result);
/**
* Start to take data to the demux's output.
diff --git a/tv/tuner/1.0/IDemuxCallback.hal b/tv/tuner/1.0/IDemuxCallback.hal
index 55e8420..7bce9ef 100644
--- a/tv/tuner/1.0/IDemuxCallback.hal
+++ b/tv/tuner/1.0/IDemuxCallback.hal
@@ -1,3 +1,19 @@
+/*
+ * 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 IDemuxCallback {
diff --git a/tv/tuner/1.0/IDescrambler.hal b/tv/tuner/1.0/IDescrambler.hal
index d078657..61ff1df 100644
--- a/tv/tuner/1.0/IDescrambler.hal
+++ b/tv/tuner/1.0/IDescrambler.hal
@@ -1,3 +1,19 @@
+/*
+ * 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;
/**
* Descrambler is used to descramble input data.
diff --git a/tv/tuner/1.0/IFrontend.hal b/tv/tuner/1.0/IFrontend.hal
index f9f78ef..962e4ba 100644
--- a/tv/tuner/1.0/IFrontend.hal
+++ b/tv/tuner/1.0/IFrontend.hal
@@ -143,7 +143,7 @@
* cable frontend.
* UNKNOWN_ERROR if failed for other reasons.
*/
- setLnb(ILnb lnb) generates (Result result);
+ setLnb(LnbId lnbId) generates (Result result);
/**
* Enble or Disable Low Noise Amplifier (LNA).
@@ -156,22 +156,4 @@
* UNKNOWN_ERROR if failed for other reasons.
*/
setLna(bool bEnable) generates (Result result);
-
- /**
- * Sends DiSEqC (Digital Satellite Equipment Control) message.
- *
- * Client sends DiSeqc message to DiSEqc compatible device through the
- * frontend. The response message from the device comes back to the client
- * through frontend's callback onDiseqcMessage.
- *
- * @param diseqcMessage a byte array of data for DiSEqC message which is
- * specified by EUTELSAT Bus Functional Specification Version 4.2.
- *
- * @return result Result status of the operation.
- * SUCCESS if successful,
- * INVALID_STATE if the frontend can't send DiSEqc Message, such as
- * cable frontend.
- * UNKNOWN_ERROR if failed for other reasons.
- */
- sendDiseqcMessage(vec<uint8_t> diseqcMessage) generates (Result result);
};
diff --git a/tv/tuner/1.0/ILnb.hal b/tv/tuner/1.0/ILnb.hal
index 49fc3b4..6b7119e 100644
--- a/tv/tuner/1.0/ILnb.hal
+++ b/tv/tuner/1.0/ILnb.hal
@@ -55,6 +55,24 @@
setSatellitePosition(FrontendLnbPosition position) generates (Result result);
/**
+ * Sends DiSEqC (Digital Satellite Equipment Control) message.
+ *
+ * Client sends DiSeqc message to DiSEqc to LNB. The response message from
+ * the device comes back to the client through frontend's callback
+ * onDiseqcMessage.
+ *
+ * @param diseqcMessage a byte array of data for DiSEqC message which is
+ * specified by EUTELSAT Bus Functional Specification Version 4.2.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * INVALID_STATE if the frontend can't send DiSEqc Message, such as
+ * cable frontend.
+ * UNKNOWN_ERROR if failed for other reasons.
+ */
+ sendDiseqcMessage(vec<uint8_t> diseqcMessage) generates (Result result);
+
+ /**
* Releases the LNB instance
*
* Associated resources are released. close may be called more than once.
diff --git a/tv/tuner/1.0/ITuner.hal b/tv/tuner/1.0/ITuner.hal
index f1a8617..0d63442 100644
--- a/tv/tuner/1.0/ITuner.hal
+++ b/tv/tuner/1.0/ITuner.hal
@@ -68,6 +68,16 @@
generates (Result result, DemuxId demuxId, IDemux demux);
/**
+ * Retrieve the Demux's Capabilities.
+ *
+ * @return result Result status of the operation.
+ * SUCCESS if successful,
+ * UNKNOWN_ERROR if the inquiry failed for other reasons.
+ * @return caps the Demux's Capabilities.
+ */
+ getDemuxCaps() generates (Result result, DemuxCapabilities caps);
+
+ /**
* Create a new instance of Descrambler.
*
* It is used by the client to create a Descrambler instance.
@@ -81,14 +91,13 @@
generates (Result result, IDescrambler descrambler);
/**
- * Create a new instance of Descrambler.
+ * Retrieve the frontend's information.
*
- * It is used by the client to create a Descrambler instance.
- *
+ * @param frontendId the id of the frontend to be inquiried.
* @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.
+ * UNKNOWN_ERROR if the inquiry failed for other reasons.
+ * @return info the frontend's information.
*/
getFrontendInfo(FrontendId frontendId)
generates (Result result, FrontendInfo info);
@@ -119,6 +128,5 @@
*/
openLnbById(LnbId lnbId)
generates (Result result, ILnb lnb);
-
};
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 889e42e..04382b0 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -67,8 +67,9 @@
0x73, 0x63, 0x65, 0x6e, 0x65,
};
-Demux::Demux(uint32_t demuxId) {
+Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
mDemuxId = demuxId;
+ mTunerService = tuner;
}
Demux::~Demux() {}
@@ -76,9 +77,20 @@
Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
ALOGV("%s", __FUNCTION__);
- mSourceFrontendId = frontendId;
+ if (mTunerService == nullptr) {
+ return Result::NOT_INITIALIZED;
+ }
- return Result::SUCCESS;
+ mFrontend = mTunerService->getFrontendById(frontendId);
+
+ if (mFrontend == nullptr) {
+ return Result::INVALID_STATE;
+ }
+
+ mFrontendSourceFile = mFrontend->getSourceFile();
+
+ mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
+ return startBroadcastInputLoop();
}
Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
@@ -100,6 +112,8 @@
mFilterEventFlags.resize(filterId + 1);
mFilterThreadRunning.resize(filterId + 1);
mFilterThreads.resize(filterId + 1);
+ mFilterPids.resize(filterId + 1);
+ mFilterOutputs.resize(filterId + 1);
}
mUsedFilterIds.insert(filterId);
@@ -142,10 +156,34 @@
return Void();
}
-Return<Result> Demux::configureFilter(uint32_t /* filterId */,
- const DemuxFilterSettings& /* settings */) {
+Return<Result> Demux::configureFilter(uint32_t filterId, const DemuxFilterSettings& settings) {
ALOGV("%s", __FUNCTION__);
+ switch (mFilterEvents[filterId].filterType) {
+ case DemuxFilterType::SECTION:
+ mFilterPids[filterId] = settings.section().tpid;
+ break;
+ case DemuxFilterType::PES:
+ mFilterPids[filterId] = settings.pesData().tpid;
+ break;
+ case DemuxFilterType::TS:
+ mFilterPids[filterId] = settings.ts().tpid;
+ break;
+ case DemuxFilterType::AUDIO:
+ mFilterPids[filterId] = settings.audio().tpid;
+ break;
+ case DemuxFilterType::VIDEO:
+ mFilterPids[filterId] = settings.video().tpid;
+ break;
+ case DemuxFilterType::RECORD:
+ mFilterPids[filterId] = settings.record().tpid;
+ break;
+ case DemuxFilterType::PCR:
+ mFilterPids[filterId] = settings.pcr().tpid;
+ break;
+ default:
+ return Result::UNKNOWN_ERROR;
+ }
return Result::SUCCESS;
}
@@ -158,36 +196,18 @@
return Result::INVALID_ARGUMENT;
}
- switch (mFilterEvents[filterId].filterType) {
- case DemuxFilterType::SECTION:
- result = startFilterLoop(filterId);
- break;
- case DemuxFilterType::PES:
- result = startPesFilterHandler(filterId);
- break;
- case DemuxFilterType::TS:
- result = startTsFilterHandler();
- return Result::SUCCESS;
- case DemuxFilterType::AUDIO:
- case DemuxFilterType::VIDEO:
- result = startMediaFilterHandler(filterId);
- break;
- case DemuxFilterType::RECORD:
- result = startRecordFilterHandler(filterId);
- break;
- case DemuxFilterType::PCR:
- result = startPcrFilterHandler();
- return Result::SUCCESS;
- default:
- return Result::UNKNOWN_ERROR;
- }
+ result = startFilterLoop(filterId);
return result;
}
-Return<Result> Demux::stopFilter(uint32_t /* filterId */) {
+Return<Result> Demux::stopFilter(uint32_t filterId) {
ALOGV("%s", __FUNCTION__);
+ mFilterThreadRunning[filterId] = false;
+
+ std::lock_guard<std::mutex> lock(mFilterThreadLock);
+
return Result::SUCCESS;
}
@@ -238,6 +258,8 @@
mFilterMQs.clear();
mFilterEvents.clear();
mFilterEventFlags.clear();
+ mFilterOutputs.clear();
+ mFilterPids.clear();
mLastUsedFilterId = -1;
return Result::SUCCESS;
@@ -277,19 +299,21 @@
return Void();
}
-Return<Result> Demux::configureOutput(const DemuxOutputSettings& /* settings */) {
+Return<Result> Demux::configureOutput(const DemuxOutputSettings& settings) {
+ ALOGV("%s", __FUNCTION__);
+
+ mOutputConfigured = true;
+ mOutputSettings = settings;
+ return Result::SUCCESS;
+}
+
+Return<Result> Demux::attachOutputFilter(uint32_t /*filterId*/) {
ALOGV("%s", __FUNCTION__);
return Result::SUCCESS;
}
-Return<Result> Demux::attachOutputTsFilter(uint32_t /*filterId*/) {
- ALOGV("%s", __FUNCTION__);
-
- return Result::SUCCESS;
-}
-
-Return<Result> Demux::detachOutputTsFilter(uint32_t /* filterId */) {
+Return<Result> Demux::detachOutputFilter(uint32_t /* filterId */) {
ALOGV("%s", __FUNCTION__);
return Result::SUCCESS;
@@ -353,15 +377,26 @@
return Void();
}
-Return<Result> Demux::configureInput(const DemuxInputSettings& /* settings */) {
+Return<Result> Demux::configureInput(const DemuxInputSettings& settings) {
ALOGV("%s", __FUNCTION__);
+ mInputConfigured = true;
+ mInputSettings = settings;
+
return Result::SUCCESS;
}
Return<Result> Demux::startInput() {
ALOGV("%s", __FUNCTION__);
+ if (!mInputCallback) {
+ return Result::NOT_INITIALIZED;
+ }
+
+ if (!mInputConfigured) {
+ return Result::INVALID_STATE;
+ }
+
pthread_create(&mInputThread, NULL, __threadLoopInput, this);
pthread_setname_np(mInputThread, "demux_input_waiting_loop");
@@ -373,6 +408,10 @@
Return<Result> Demux::stopInput() {
ALOGV("%s", __FUNCTION__);
+ mInputThreadRunning = false;
+
+ std::lock_guard<std::mutex> lock(mInputThreadLock);
+
return Result::SUCCESS;
}
@@ -403,36 +442,52 @@
return Result::SUCCESS;
}
-Result Demux::startSectionFilterHandler(uint32_t filterId, vector<uint8_t> data) {
- if (!writeSectionsAndCreateEvent(filterId, data)) {
+Result Demux::startSectionFilterHandler(uint32_t filterId) {
+ if (mFilterOutputs[filterId].empty()) {
+ return Result::SUCCESS;
+ }
+ if (!writeSectionsAndCreateEvent(filterId, mFilterOutputs[filterId])) {
ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
return Result::UNKNOWN_ERROR;
}
+ mFilterOutputs[filterId].clear();
+
return Result::SUCCESS;
}
Result Demux::startPesFilterHandler(uint32_t filterId) {
- // TODO generate multiple events in one event callback
+ std::lock_guard<std::mutex> lock(mFilterEventLock);
DemuxFilterPesEvent pesEvent;
- pesEvent = {
- // temp dump meta data
- .streamId = 0,
- .dataLength = 530,
- };
- mFilterEvents[filterId].events.resize(1);
- mFilterEvents[filterId].events[0].pes(pesEvent);
- /*pthread_create(&mThreadId, NULL, __threadLoop, this);
- pthread_setname_np(mThreadId, "demux_section_filter_waiting_loop");*/
- if (!writeDataToFilterMQ(fakeDataInputBuffer, filterId)) {
- return Result::INVALID_STATE;
+ if (mFilterOutputs[filterId].empty()) {
+ return Result::SUCCESS;
}
- if (mDemuxCallbacks[filterId] == nullptr) {
- return Result::NOT_INITIALIZED;
+ for (int i = 0; i < mFilterOutputs[filterId].size(); i += 188) {
+ uint8_t pusi = mFilterOutputs[filterId][i + 1] & 0x40;
+ uint8_t adaptFieldControl = (mFilterOutputs[filterId][i + 3] & 0x30) >> 4;
+ ALOGD("[Demux] pusi %d, adaptFieldControl %d", pusi, adaptFieldControl);
+ if (pusi && (adaptFieldControl == 0x01)) {
+ vector<uint8_t>::const_iterator first = mFilterOutputs[filterId].begin() + i + 4;
+ vector<uint8_t>::const_iterator last = mFilterOutputs[filterId].begin() + i + 187;
+ vector<uint8_t> filterOutData(first, last);
+ if (!writeDataToFilterMQ(filterOutData, filterId)) {
+ mFilterOutputs[filterId].clear();
+ return Result::INVALID_STATE;
+ }
+ pesEvent = {
+ // temp dump meta data
+ .streamId = filterOutData[3],
+ .dataLength = static_cast<uint16_t>(filterOutData.size()),
+ };
+ int size = mFilterEvents[filterId].events.size();
+ mFilterEvents[filterId].events.resize(size + 1);
+ mFilterEvents[filterId].events[size].pes(pesEvent);
+ }
}
- mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
+ mFilterOutputs[filterId].clear();
+
return Result::SUCCESS;
}
@@ -451,6 +506,8 @@
};
mFilterEvents[filterId].events.resize(1);
mFilterEvents[filterId].events[0].media() = mediaEvent;
+
+ mFilterOutputs[filterId].clear();
// TODO handle write FQM for media stream
return Result::SUCCESS;
}
@@ -465,6 +522,8 @@
recordEvent.indexMask.tsIndexMask() = 0x01;
mFilterEvents[filterId].events.resize(1);
mFilterEvents[filterId].events[0].ts() = recordEvent;
+
+ mFilterOutputs[filterId].clear();
return Result::SUCCESS;
}
@@ -499,18 +558,18 @@
bool Demux::writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data) {
// TODO check how many sections has been read
std::lock_guard<std::mutex> lock(mFilterEventLock);
- int size = mFilterEvents[filterId].events.size();
- mFilterEvents[filterId].events.resize(size + 1);
if (!writeDataToFilterMQ(data, filterId)) {
return false;
}
+ int size = mFilterEvents[filterId].events.size();
+ mFilterEvents[filterId].events.resize(size + 1);
DemuxFilterSectionEvent secEvent;
secEvent = {
// temp dump meta data
.tableId = 0,
.version = 1,
.sectionNum = 1,
- .dataLength = 530,
+ .dataLength = static_cast<uint16_t>(data.size()),
};
mFilterEvents[filterId].events[size].section(secEvent);
return true;
@@ -524,21 +583,44 @@
return false;
}
-bool Demux::filterAndOutputData() {
- ALOGD("[Demux] start to dispatch data to filters");
+bool Demux::readInputFMQ() {
// Read input data from the input FMQ
int size = mInputMQ->availableToRead();
+ int inputPacketSize = mInputSettings.packetSize;
vector<uint8_t> dataOutputBuffer;
- dataOutputBuffer.resize(size);
- mInputMQ->read(dataOutputBuffer.data(), size);
+ dataOutputBuffer.resize(inputPacketSize);
- Result result;
- // Filter the data and feed the output to each filter
+ // Dispatch the packet to the PID matching filter output buffer
+ for (int i = 0; i < size / inputPacketSize; i++) {
+ if (!mInputMQ->read(dataOutputBuffer.data(), inputPacketSize)) {
+ return false;
+ }
+ startTsFilter(dataOutputBuffer);
+ }
+
+ return true;
+}
+
+void Demux::startTsFilter(vector<uint8_t> data) {
set<uint32_t>::iterator it;
for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+ uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
+ ALOGW("start ts filter pid: %d", pid);
+ if (pid == mFilterPids[*it]) {
+ mFilterOutputs[*it].insert(mFilterOutputs[*it].end(), data.begin(), data.end());
+ }
+ }
+}
+
+bool Demux::startFilterDispatcher() {
+ Result result;
+ set<uint32_t>::iterator it;
+
+ // Handle the output data per filter type
+ for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
switch (mFilterEvents[*it].filterType) {
case DemuxFilterType::SECTION:
- result = startSectionFilterHandler(*it, dataOutputBuffer);
+ result = startSectionFilterHandler(*it);
break;
case DemuxFilterType::PES:
result = startPesFilterHandler(*it);
@@ -578,6 +660,7 @@
void Demux::filterThreadLoop(uint32_t filterId) {
ALOGD("[Demux] filter %d threadLoop start.", filterId);
+ std::lock_guard<std::mutex> lock(mFilterThreadLock);
mFilterThreadRunning[filterId] = true;
// For the first time of filter output, implementation needs to send the filter
@@ -640,6 +723,7 @@
void Demux::inputThreadLoop() {
ALOGD("[Demux] input threadLoop start.");
+ std::lock_guard<std::mutex> lock(mInputThreadLock);
mInputThreadRunning = true;
while (mInputThreadRunning) {
@@ -653,16 +737,110 @@
}
// Our current implementation filter the data and write it into the filter FMQ immedaitely
// after the DATA_READY from the VTS/framework
- if (!filterAndOutputData()) {
+ if (!readInputFMQ() || !startFilterDispatcher()) {
ALOGD("[Demux] input data failed to be filtered. Ending thread");
break;
}
+
+ maySendInputStatusCallback();
}
mInputThreadRunning = false;
ALOGD("[Demux] input thread ended.");
}
+void Demux::maySendInputStatusCallback() {
+ std::lock_guard<std::mutex> lock(mInputStatusLock);
+ int availableToRead = mInputMQ->availableToRead();
+ int availableToWrite = mInputMQ->availableToWrite();
+
+ DemuxInputStatus newStatus =
+ checkStatusChange(availableToWrite, availableToRead, mInputSettings.highThreshold,
+ mInputSettings.lowThreshold);
+ if (mIntputStatus != newStatus) {
+ mInputCallback->onInputStatus(newStatus);
+ mIntputStatus = newStatus;
+ }
+}
+
+DemuxInputStatus Demux::checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+ uint32_t highThreshold, uint32_t lowThreshold) {
+ if (availableToWrite == 0) {
+ return DemuxInputStatus::SPACE_FULL;
+ } else if (availableToRead > highThreshold) {
+ return DemuxInputStatus::SPACE_ALMOST_FULL;
+ } else if (availableToRead < lowThreshold) {
+ return DemuxInputStatus::SPACE_ALMOST_EMPTY;
+ } else if (availableToRead == 0) {
+ return DemuxInputStatus::SPACE_EMPTY;
+ }
+ return mIntputStatus;
+}
+
+Result Demux::startBroadcastInputLoop() {
+ pthread_create(&mBroadcastInputThread, NULL, __threadLoopBroadcast, this);
+ pthread_setname_np(mBroadcastInputThread, "broadcast_input_thread");
+
+ return Result::SUCCESS;
+}
+
+void* Demux::__threadLoopBroadcast(void* user) {
+ Demux* const self = static_cast<Demux*>(user);
+ self->broadcastInputThreadLoop();
+ return 0;
+}
+
+void Demux::broadcastInputThreadLoop() {
+ std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
+ mBroadcastInputThreadRunning = true;
+ mKeepFetchingDataFromFrontend = true;
+
+ // open the stream and get its length
+ std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
+ // TODO take the packet size from the frontend setting
+ int packetSize = 188;
+ int writePacketAmount = 6;
+ char* buffer = new char[packetSize];
+ ALOGW("[Demux] broadcast input thread loop start %s", mFrontendSourceFile.c_str());
+ if (!inputData.is_open()) {
+ mBroadcastInputThreadRunning = false;
+ ALOGW("[Demux] Error %s", strerror(errno));
+ }
+
+ while (mBroadcastInputThreadRunning) {
+ // move the stream pointer for packet size * 6 every read until the end
+ while (mKeepFetchingDataFromFrontend) {
+ for (int i = 0; i < writePacketAmount; i++) {
+ inputData.read(buffer, packetSize);
+ if (!inputData) {
+ mBroadcastInputThreadRunning = false;
+ break;
+ }
+ // filter and dispatch filter output
+ vector<uint8_t> byteBuffer;
+ byteBuffer.resize(sizeof(buffer));
+ for (int index = 0; index < byteBuffer.size(); index++) {
+ byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
+ }
+ startTsFilter(byteBuffer);
+ inputData.seekg(packetSize, inputData.cur);
+ }
+ startFilterDispatcher();
+ sleep(1);
+ }
+ }
+
+ ALOGW("[Demux] Broadcast Input thread end.");
+ delete[] buffer;
+ inputData.close();
+}
+
+void Demux::stopBroadcastInput() {
+ mKeepFetchingDataFromFrontend = false;
+ mBroadcastInputThreadRunning = false;
+ std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 2fdde8d..e4a4e2b 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -20,6 +20,8 @@
#include <android/hardware/tv/tuner/1.0/IDemux.h>
#include <fmq/MessageQueue.h>
#include <set>
+#include "Frontend.h"
+#include "Tuner.h"
using namespace std;
@@ -40,9 +42,12 @@
using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+class Tuner;
+class Frontend;
+
class Demux : public IDemux {
public:
- Demux(uint32_t demuxId);
+ Demux(uint32_t demuxId, sp<Tuner> tuner);
~Demux();
@@ -91,9 +96,9 @@
virtual Return<Result> configureOutput(const DemuxOutputSettings& settings) override;
- virtual Return<Result> attachOutputTsFilter(uint32_t filterId) override;
+ virtual Return<Result> attachOutputFilter(uint32_t filterId) override;
- virtual Return<Result> detachOutputTsFilter(uint32_t filterId) override;
+ virtual Return<Result> detachOutputFilter(uint32_t filterId) override;
virtual Return<Result> startOutput() override;
@@ -103,7 +108,17 @@
virtual Return<Result> removeOutput() override;
+ // Functions interacts with Tuner Service
+ void stopBroadcastInput();
+
private:
+ // Tuner service
+ sp<Tuner> mTunerService;
+
+ // Frontend source
+ sp<Frontend> mFrontend;
+ string mFrontendSourceFile;
+
// A struct that passes the arguments to a newly created filter thread
struct ThreadArgs {
Demux* user;
@@ -115,13 +130,14 @@
* They are also responsible to write the filtered output into the filter FMQ
* and update the filterEvent bound with the same filterId.
*/
- Result startSectionFilterHandler(uint32_t filterId, vector<uint8_t> data);
+ Result startSectionFilterHandler(uint32_t filterId);
Result startPesFilterHandler(uint32_t filterId);
Result startTsFilterHandler();
Result startMediaFilterHandler(uint32_t filterId);
Result startRecordFilterHandler(uint32_t filterId);
Result startPcrFilterHandler();
Result startFilterLoop(uint32_t filterId);
+ Result startBroadcastInputLoop();
/**
* To create a FilterMQ with the the next available Filter ID.
@@ -136,18 +152,24 @@
bool writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId);
bool readDataFromMQ();
bool writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data);
+ void maySendInputStatusCallback();
+ DemuxInputStatus checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+ uint32_t highThreshold, uint32_t lowThreshold);
/**
* A dispatcher to read and dispatch input data to all the started filters.
* Each filter handler handles the data filtering/output writing/filterEvent updating.
*/
- bool filterAndOutputData();
+ bool readInputFMQ();
+ void startTsFilter(vector<uint8_t> data);
+ bool startFilterDispatcher();
static void* __threadLoopFilter(void* data);
static void* __threadLoopInput(void* user);
+ static void* __threadLoopBroadcast(void* user);
void filterThreadLoop(uint32_t filterId);
void inputThreadLoop();
+ void broadcastInputThreadLoop();
uint32_t mDemuxId;
- uint32_t mSourceFrontendId;
/**
* Record the last used filter id. Initial value is -1.
* Filter Id starts with 0.
@@ -169,6 +191,8 @@
* A list of created FilterMQ ptrs.
* The array number is the filter ID.
*/
+ vector<uint16_t> mFilterPids;
+ vector<vector<uint8_t>> mFilterOutputs;
vector<unique_ptr<FilterMQ>> mFilterMQs;
vector<EventFlag*> mFilterEventFlags;
vector<DemuxFilterEvent> mFilterEvents;
@@ -182,15 +206,26 @@
vector<sp<IDemuxCallback>> mDemuxCallbacks;
sp<IDemuxCallback> mInputCallback;
sp<IDemuxCallback> mOutputCallback;
+ bool mInputConfigured = false;
+ bool mOutputConfigured = false;
+ DemuxInputSettings mInputSettings;
+ DemuxOutputSettings mOutputSettings;
+
// Thread handlers
pthread_t mInputThread;
pthread_t mOutputThread;
+ pthread_t mBroadcastInputThread;
vector<pthread_t> mFilterThreads;
+
+ // FMQ status local records
+ DemuxInputStatus mIntputStatus;
/**
* If a specific filter's writing loop is still running
*/
vector<bool> mFilterThreadRunning;
bool mInputThreadRunning;
+ bool mBroadcastInputThreadRunning;
+ bool mKeepFetchingDataFromFrontend;
/**
* Lock to protect writes to the FMQs
*/
@@ -198,8 +233,16 @@
/**
* Lock to protect writes to the filter event
*/
+ // TODO make each filter separate event lock
std::mutex mFilterEventLock;
/**
+ * Lock to protect writes to the input status
+ */
+ std::mutex mInputStatusLock;
+ std::mutex mBroadcastInputThreadLock;
+ std::mutex mFilterThreadLock;
+ std::mutex mInputThreadLock;
+ /**
* How many times a filter should write
* TODO make this dynamic/random/can take as a parameter
*/
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 0609d05..1e07edd 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -27,14 +27,10 @@
namespace V1_0 {
namespace implementation {
-Frontend::Frontend() {
- // Init callback to nullptr
- mCallback = nullptr;
-}
-
-Frontend::Frontend(FrontendType type, FrontendId id) {
+Frontend::Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner) {
mType = type;
mId = id;
+ mTunerService = tuner;
// Init callback to nullptr
mCallback = nullptr;
}
@@ -67,13 +63,18 @@
return Result::INVALID_STATE;
}
- mCallback->onEvent(FrontendEventType::NO_SIGNAL);
+ // TODO dynamically allocate file to the source file
+ mSourceStreamFile = FRONTEND_STREAM_FILE;
+
+ mCallback->onEvent(FrontendEventType::LOCKED);
return Result::SUCCESS;
}
Return<Result> Frontend::stopTune() {
ALOGV("%s", __FUNCTION__);
+ mTunerService->frontendStopTune(mId);
+
return Result::SUCCESS;
}
@@ -105,13 +106,7 @@
return Result::SUCCESS;
}
-Return<Result> Frontend::setLnb(const sp<ILnb>& /* lnb */) {
- ALOGV("%s", __FUNCTION__);
-
- return Result::SUCCESS;
-}
-
-Return<Result> Frontend::sendDiseqcMessage(const hidl_vec<uint8_t>& /* diseqcMessage */) {
+Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
ALOGV("%s", __FUNCTION__);
return Result::SUCCESS;
@@ -125,6 +120,10 @@
return mId;
}
+string Frontend::getSourceFile() {
+ return mSourceStreamFile;
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index fc586b5..07fa7b9 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -18,7 +18,9 @@
#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>
+#include <fstream>
+#include <iostream>
+#include "Tuner.h"
using namespace std;
@@ -35,11 +37,11 @@
using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::Result;
+class Tuner;
+
class Frontend : public IFrontend {
public:
- Frontend();
-
- Frontend(FrontendType type, FrontendId id);
+ Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner);
virtual Return<Result> close() override;
@@ -56,21 +58,26 @@
virtual Return<void> getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
getStatus_cb _hidl_cb) override;
- virtual Return<Result> sendDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
-
virtual Return<Result> setLna(bool bEnable) override;
- virtual Return<Result> setLnb(const sp<ILnb>& lnb) override;
+ virtual Return<Result> setLnb(uint32_t lnb) override;
FrontendType getFrontendType();
FrontendId getFrontendId();
+ string getSourceFile();
+
private:
virtual ~Frontend();
sp<IFrontendCallback> mCallback;
+ sp<Tuner> mTunerService;
FrontendType mType = FrontendType::UNDEFINED;
FrontendId mId = 0;
+
+ const string FRONTEND_STREAM_FILE = "/vendor/etc/test1.ts";
+ string mSourceStreamFile;
+ std::ifstream mFrontendData;
};
} // namespace implementation
diff --git a/tv/tuner/1.0/default/Lnb.cpp b/tv/tuner/1.0/default/Lnb.cpp
index b81bb15..1446f7f 100644
--- a/tv/tuner/1.0/default/Lnb.cpp
+++ b/tv/tuner/1.0/default/Lnb.cpp
@@ -48,6 +48,12 @@
return Result::SUCCESS;
}
+Return<Result> Lnb::sendDiseqcMessage(const hidl_vec<uint8_t>& /* diseqcMessage */) {
+ ALOGV("%s", __FUNCTION__);
+
+ return Result::SUCCESS;
+}
+
Return<Result> Lnb::close() {
ALOGV("%s", __FUNCTION__);
diff --git a/tv/tuner/1.0/default/Lnb.h b/tv/tuner/1.0/default/Lnb.h
index df7e0fe..4c251f7 100644
--- a/tv/tuner/1.0/default/Lnb.h
+++ b/tv/tuner/1.0/default/Lnb.h
@@ -38,12 +38,14 @@
public:
Lnb();
- virtual Return<Result> setVoltage(FrontendLnbVoltage voltage);
+ virtual Return<Result> setVoltage(FrontendLnbVoltage voltage) override;
virtual Return<Result> setTone(FrontendLnbTone tone) override;
virtual Return<Result> setSatellitePosition(FrontendLnbPosition position) override;
+ virtual Return<Result> sendDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
virtual Return<Result> close() override;
private:
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 00831ae..f86b28d 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -38,14 +38,14 @@
// 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);
+ mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this);
+ mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this);
+ mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this);
+ mFrontends[3] = new Frontend(FrontendType::DVBS, 3, this);
+ mFrontends[4] = new Frontend(FrontendType::DVBT, 4, this);
+ mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this);
+ mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this);
+ mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
}
Tuner::~Tuner() {}
@@ -81,12 +81,22 @@
DemuxId demuxId = mLastUsedId + 1;
mLastUsedId += 1;
- sp<IDemux> demux = new Demux(demuxId);
+ sp<Demux> demux = new Demux(demuxId, this);
+ mDemuxes[demuxId] = demux;
_hidl_cb(Result::SUCCESS, demuxId, demux);
return Void();
}
+Return<void> Tuner::getDemuxCaps(getDemuxCaps_cb _hidl_cb) {
+ ALOGV("%s", __FUNCTION__);
+
+ DemuxCapabilities caps;
+
+ _hidl_cb(Result::SUCCESS, caps);
+ return Void();
+}
+
Return<void> Tuner::openDescrambler(openDescrambler_cb _hidl_cb) {
ALOGV("%s", __FUNCTION__);
@@ -123,6 +133,25 @@
return Void();
}
+sp<Frontend> Tuner::getFrontendById(uint32_t frontendId) {
+ ALOGV("%s", __FUNCTION__);
+
+ return mFrontends[frontendId];
+}
+
+void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
+ mFrontendToDemux[frontendId] = demuxId;
+}
+
+void Tuner::frontendStopTune(uint32_t frontendId) {
+ map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
+ uint32_t demuxId;
+ if (it != mFrontendToDemux.end()) {
+ demuxId = it->second;
+ mDemuxes[demuxId]->stopBroadcastInput();
+ }
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace tuner
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
index 62227ee..96da257 100644
--- a/tv/tuner/1.0/default/Tuner.h
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -18,6 +18,8 @@
#define ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <map>
+#include "Demux.h"
#include "Frontend.h"
using namespace std;
@@ -29,6 +31,9 @@
namespace V1_0 {
namespace implementation {
+class Frontend;
+class Demux;
+
class Tuner : public ITuner {
public:
Tuner();
@@ -39,6 +44,8 @@
virtual Return<void> openDemux(openDemux_cb _hidl_cb) override;
+ virtual Return<void> getDemuxCaps(getDemuxCaps_cb _hidl_cb) override;
+
virtual Return<void> openDescrambler(openDescrambler_cb _hidl_cb) override;
virtual Return<void> getFrontendInfo(FrontendId frontendId,
@@ -48,10 +55,18 @@
virtual Return<void> openLnbById(LnbId lnbId, openLnbById_cb _hidl_cb) override;
+ sp<Frontend> getFrontendById(uint32_t frontendId);
+
+ void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
+
+ void frontendStopTune(uint32_t frontendId);
+
private:
virtual ~Tuner();
// Static mFrontends array to maintain local frontends information
vector<sp<Frontend>> mFrontends;
+ std::map<uint32_t, uint32_t> mFrontendToDemux;
+ std::map<uint32_t, sp<Demux>> mDemuxes;
// To maintain how many Frontends we have
int mFrontendSize;
// The last used demux id. Initial value is -1.
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
index a1153e9..897818b 100644
--- a/tv/tuner/1.0/types.hal
+++ b/tv/tuner/1.0/types.hal
@@ -43,7 +43,7 @@
ANALOG,
/* Advanced Television Systems Committee (ATSC) Standard A/72. */
ATSC,
- /* Advanced Television Systems Committee (ATSC 3.0) Standard A/330. */
+ /* Advanced Television Systems Committee (ATSC 3.0) Standard A/300. */
ATSC3,
/**
* Digital Video Broadcasting - Cable
@@ -63,11 +63,11 @@
*/
DVBT,
/* Integrated Services Digital Broadcasting-Satellite (ISDB-S)
- * ARIB SDT-B20 is technical document of ISDB-S.
+ * ARIB STD-B20 is technical document of ISDB-S.
*/
ISDBS,
/* Integrated Services Digital Broadcasting-Satellite (ISDB-S)
- * ARIB TR-B15 is technical document of ISDB-S3.
+ * ARIB STD-B44 is technical document of ISDB-S3.
*/
ISDBS3,
/* Integrated Services Digital Broadcasting-Terrestrial (ISDB-T or SBTVD)
@@ -164,8 +164,10 @@
@export
enum FrontendAtscModulation : uint32_t {
UNDEFINED = 0,
- MOD_8VSB = 1 << 0,
- MOD_16VSB = 1 << 1,
+ /** hardware is able to detect and set modulation automatically */
+ AUTO = 1 << 0,
+ MOD_8VSB = 1 << 2,
+ MOD_16VSB = 1 << 3,
};
/**
@@ -191,12 +193,14 @@
@export
enum FrontendAtsc3Modulation : uint32_t {
UNDEFINED = 0,
- MOD_QPSK = 1 << 0,
- MOD_16QAM = 1 << 1,
- MOD_64QAM = 1 << 2,
- MOD_256QAM = 1 << 3,
- MOD_1024QAM = 1 << 4,
- MOD_4096QAM = 1 << 5,
+ /** hardware is able to detect and set modulation automatically */
+ AUTO = 1 << 0,
+ MOD_QPSK = 1 << 1,
+ MOD_16QAM = 1 << 2,
+ MOD_64QAM = 1 << 3,
+ MOD_256QAM = 1 << 4,
+ MOD_1024QAM = 1 << 5,
+ MOD_4096QAM = 1 << 6,
};
/**
@@ -205,9 +209,11 @@
@export
enum FrontendAtsc3Bandwidth : uint32_t {
UNDEFINED = 0,
- BANDWIDTH_8MHZ = 1 << 0,
- BANDWIDTH_7MHZ = 1 << 1,
- BANDWIDTH_6MHZ = 1 << 2,
+ /** hardware is able to detect and set bandwidth automatically */
+ AUTO = 1 << 0,
+ BANDWIDTH_6MHZ = 1 << 1,
+ BANDWIDTH_7MHZ = 1 << 2,
+ BANDWIDTH_8MHZ = 1 << 3,
};
/**
@@ -215,9 +221,11 @@
*/
@export
enum FrontendAtsc3TimeInterleaveMode : uint32_t {
- UNDEFINED,
- CTI,
- HTI,
+ UNDEFINED = 0,
+ /** hardware is able to detect and set TimeInterleaveMode automatically */
+ AUTO = 1 << 0,
+ CTI = 1 << 1,
+ HTI = 1 << 2,
};
/**
@@ -247,13 +255,39 @@
*/
@export
enum FrontendAtsc3Fec : uint32_t {
- UNDEFINED,
- BCH_LDPC_16K,
- BCH_LDPC_64K,
- CRC_LDPC_16K,
- CRC_LDPC_64K,
- LDPC_16K,
- LDPC_64K,
+ UNDEFINED = 0,
+ /** hardware is able to detect and set FEC automatically */
+ AUTO = 1 << 0,
+ BCH_LDPC_16K = 1 << 1,
+ BCH_LDPC_64K = 1 << 2,
+ CRC_LDPC_16K = 1 << 3,
+ CRC_LDPC_64K = 1 << 4,
+ LDPC_16K = 1 << 5,
+ LDPC_64K = 1 << 6,
+};
+
+/**
+ * Demodulator Output Format for an ATSC3 Frontend.
+ */
+@export
+enum FrontendAtsc3DemodOutputFormat : uint8_t {
+ /** Dummy. Scan uses this. */
+ UNDEFINED = 0,
+ /** ALP format. Typically used in US region. */
+ ATSC3_LINKLAYER_PACKET = 1 << 0,
+ /** BaseBand packet format. Typically used in Korea region. */
+ BASEBAND_PACKET = 1 << 1,
+};
+
+/**
+ * PLP basis Signal Settings for an ATSC3 Frontend.
+ */
+struct FrontendAtsc3PlpSettings {
+ uint8_t plpId;
+ FrontendAtsc3Modulation modulation;
+ FrontendAtsc3TimeInterleaveMode interleaveMode;
+ FrontendAtsc3CodeRate codeRate;
+ FrontendAtsc3Fec fec;
};
/**
@@ -262,21 +296,28 @@
struct FrontendAtsc3Settings {
/** Signal frequency in Hertz */
uint32_t frequency;
+ /** Bandwidth of tuning band. */
FrontendAtsc3Bandwidth bandwidth;
- FrontendAtsc3TimeInterleaveMode interleaveMode;
- FrontendAtsc3CodeRate codeRate;
- FrontendAtsc3Fec fec;
- vec<uint8_t> plpIdList;
+ FrontendAtsc3DemodOutputFormat demodOutputFormat;
+ vec<FrontendAtsc3PlpSettings> plpSettings;
};
/**
* Capabilities for ATSC3 Frontend.
*/
struct FrontendAtsc3Capabilities {
- /** Modulation capability */
- bitfield<FrontendAtsc3Modulation> modulationCap;
/** Bandwidth capability */
bitfield<FrontendAtsc3Bandwidth> bandwidthCap;
+ /** Modulation capability */
+ bitfield<FrontendAtsc3Modulation> modulationCap;
+ /** TimeInterleaveMode capability */
+ bitfield<FrontendAtsc3TimeInterleaveMode> timeInterleaveModeCap;
+ /** CodeRate capability */
+ bitfield<FrontendAtsc3CodeRate> codeRateCap;
+ /** FEC capability */
+ bitfield<FrontendAtsc3Fec> fecCap;
+ /** Demodulator Output Format capability */
+ bitfield<FrontendAtsc3DemodOutputFormat> demodOutputFormatCap;
};
/**
@@ -647,7 +688,7 @@
@export
enum FrontendIsdbsStreamIdType : uint32_t {
STREAM_ID,
- RELATIVE_STREAM_ID,
+ RELATIVE_STREAM_NUMBER,
};
/**
@@ -845,6 +886,7 @@
M_EIA_J = 1 << 13,
I_NICAM = 1 << 14,
L_NICAM = 1 << 15,
+ L_PRIME = 1 << 16,
};
/**
@@ -907,10 +949,20 @@
PLP_IDS,
/** Locked group Ids for DVBT2 frontend. */
GROUP_IDS,
- /** Locked the number of the Plps. */
- INPUT_STREAM_IDS,
+ /** Stream Ids. */
+ INPUT_STREAM_IDS,
/** Locked signal stardard. */
STANDARD,
+ /** PLP status in a tuned frequency band for ATSC3 frontend. */
+ ATSC3_PLP_INFO,
+};
+
+/**
+ * ATSC3.0 PLP information for scan
+ */
+struct FrontendScanAtsc3PlpInfo {
+ uint8_t plpId;
+ bool bLlsFlag;
};
/**
@@ -927,11 +979,13 @@
uint32_t symbolRate;
vec<uint8_t> plpIds;
vec<uint8_t> groupIds;
- vec<uint8_t> inputStreamIds;
+ vec<uint16_t> inputStreamIds;
safe_union standard {
FrontendDvbsStandard sStd;
FrontendDvbtStandard tStd;
} std;
+ /** A list of PLP status in a tuned frequency band for ATSC3 frontend. */
+ vec<FrontendScanAtsc3PlpInfo> atsc3PlpInfos;
};
/**
@@ -940,17 +994,17 @@
@export
enum FrontendEventType : uint32_t {
/**
- * If frontend locked the signal which is specified by tune method, HAL sent
+ * If frontend locked the signal which is specified by tune method, HAL sends
* Locked event.
*/
LOCKED,
/**
* If frontend can't locked the signal which is specified by tune method,
- * HAL sent NO_SIGNAL event.
+ * HAL sends NO_SIGNAL event.
*/
NO_SIGNAL,
/**
- * If frontend detect that the locked signal get lost, HAL sent LOST_LOCK
+ * If frontend detect that the locked signal get lost, HAL sends LOST_LOCK
* event.
*/
LOST_LOCK,
@@ -977,15 +1031,15 @@
*/
@export
enum FrontendStatusType : uint32_t {
- /** Lock status for RF or Demod. */
- LOCK,
+ /** Lock status for Demod. */
+ DEMOD_LOCK,
/** Signal to Noise Ratio. */
SNR,
/** Bit Error Ratio. */
BER,
/** Packages Error Ratio. */
PER,
- /** Bit Error Ratio befor FEC. */
+ /** Bit Error Ratio before FEC. */
PRE_BER,
/*
* Signal Quality (0..100). Good data over total data in percent can be
@@ -993,7 +1047,7 @@
*/
SIGNAL_QUALITY,
/** Signal Strength. */
- SIGGAL_STRENGTH,
+ SIGNAL_STRENGTH,
/** Symbol Rate. */
SYMBOL_RATE,
/** Forward Error Correction Type. */
@@ -1008,21 +1062,62 @@
PLP_ID,
/** Status for Emergency Warning Broadcasting System. */
EWBS,
+ /** Automatic Gain Control. */
+ AGC,
+ /** Low Noise Amplifier. */
+ LNA,
+ /** Lock status for stream. */
+ STREAM_LOCK,
+ /** Error status by layer. */
+ LAYER_ERROR,
+ /** CN value by VBER. */
+ VBER_CN,
+ /** CN value by LBER. */
+ LBER_CN,
+ /** CN value by XER. */
+ XER_CN,
+ /** Moduration Error Ratio. */
+ MER,
+ /** Difference between tuning frequency and actual locked frequency. */
+ FREQ_OFFSET,
+ /* Hierarchy for DVBT. */
+ HIERARCHY,
+ /** Lock status for RF. */
+ RF_LOCK,
+ /** PLP information in a frequency band for ATSC3.0 frontend. */
+ ATSC3_PLP_INFO,
};
/**
+ * Status for each tuning PLPs
+ */
+struct FrontendStatusAtsc3PlpInfo {
+ /** PLP Id value. */
+ uint8_t plpId;
+ /** Demod Lock/Unlock status of this particular PLP. */
+ bool isLocked;
+ /** Uncorrectable Error Counts (UEC) of this particular PLP since last tune operation. */
+ uint32_t uec;
+};
+
+
+/**
* Modulation Type for Frontend's status.
*/
safe_union FrontendModulationStatus {
+ FrontendDvbcModulation dvbc;
FrontendDvbsModulation dvbs;
- FrontendAtsc3Modulation atsc3;
+ FrontendIsdbsModulation isdbs;
+ FrontendIsdbs3Modulation isdbs3;
+ FrontendIsdbtModulation isdbt;
};
/**
* The status for Frontend.
*/
safe_union FrontendStatus {
- bool isLocked;
+ /** Lock status for Demod in True/False. */
+ bool isDemodLocked;
/** SNR value measured by 0.001 dB. */
int32_t snr;
/** The number of error bit per 1 billion bits. */
@@ -1043,6 +1138,25 @@
FrontendLnbVoltage lnbVoltage;
uint8_t plpId;
bool isEWBS;
+ /** AGC value is normalized from 0 to 255. */
+ uint8_t agc;
+ bool isLnaOn;
+ bool isStreamLock;
+ vec<bool> isLayerError;
+ /** CN value by VBER measured by 0.001 dB */
+ int32_t vberCn;
+ /** CN value by LBER measured by 0.001 dB */
+ int32_t lberCn;
+ /** CN value by XER measured by 0.001 dB */
+ int32_t xerCn;
+ /** MER value measured by 0.001 dB */
+ int32_t mer;
+ /** Frequency difference in Hertz. */
+ int32_t freqOffset;
+ FrontendDvbtHierarchy hierarchy;
+ bool isRfLocked;
+ /** A list of PLP status for tuned PLPs for ATSC3 frontend. */
+ vec<FrontendStatusAtsc3PlpInfo> plpInfo;
};
/**
@@ -1121,7 +1235,6 @@
POSITION_B,
};
-
/* Demux ID is used to associate with a hardware demux resource. */
typedef uint32_t DemuxId;
@@ -1150,7 +1263,7 @@
*/
AUDIO,
/**
- * A filter to filter Vidoe Metadata out from input stream.
+ * A filter to filter Video Metadata out from input stream.
*/
VIDEO,
/**
@@ -1475,6 +1588,8 @@
PES,
/* Data is Elementary Stream. */
ES,
+ /* Data is TLV (type-length-value) Stream for JP SHV */
+ SHV_TLV,
};
/**
@@ -1534,6 +1649,10 @@
SPACE_FULL = 1 << 3,
};
+/**
+ * The Settings for the demux's input.
+ */
+@export
struct DemuxInputSettings {
/**
* Register for interested status events so that the HAL can send these
@@ -1559,3 +1678,30 @@
*/
uint8_t packetSize;
};
+
+/**
+ * Capabilities for Demux.
+ */
+@export
+struct DemuxCapabilities {
+ /* The number of Demux to be supported. */
+ uint32_t numDemux;
+ /* The number of Input to be supported. */
+ uint32_t numInput;
+ /* The number of Output to be supported. */
+ uint32_t numOutput;
+ /* The number of TS Filter to be supported. */
+ uint32_t numTsFilter;
+ /* The number of Section Filter to be supported. */
+ uint32_t numSectionFilter;
+ /* The number of Audio Filter to be supported. */
+ uint32_t numAudioFilter;
+ /* The number of Video Filter to be supported. */
+ uint32_t numVideoFilter;
+ /* The number of PES Filter to be supported. */
+ uint32_t numPesFilter;
+ /* The number of PCR Filter to be supported. */
+ uint32_t numPcrFilter;
+ /* The maximum number of bytes is supported in the mask of Section Filter. */
+ uint32_t numBytesInSectionFilter;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 7256cc4..7936185 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -39,6 +39,7 @@
#include <map>
#define WAIT_TIMEOUT 3000000000
+#define WAIT_TIMEOUT_data_ready 3000000000 * 4
using android::Condition;
using android::IMemory;
@@ -58,8 +59,10 @@
using android::hardware::Void;
using android::hardware::tv::tuner::V1_0::DemuxDataFormat;
using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
using android::hardware::tv::tuner::V1_0::DemuxFilterType;
@@ -130,9 +133,6 @@
const uint16_t FMQ_SIZE_4K = 0x1000;
const uint32_t FMQ_SIZE_1M = 0x100000;
-// Equal to SECTION_WRITE_COUNT on the HAL impl side
-// The HAL impl will repeatedly write to the FMQ the count times
-const uint16_t SECTION_READ_COUNT = 10;
struct FilterConf {
DemuxFilterType type;
@@ -214,11 +214,15 @@
class DemuxCallback : public IDemuxCallback {
public:
virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
- ALOGW("[VTS] FILTER EVENT %d", filterEvent.filterId);
android::Mutex::Autolock autoLock(mMsgLock);
- mFilterEventReceived = true;
+ // Temprarily we treat the first coming back filter data on the matching pid a success
+ // once all of the MQ are cleared, means we got all the expected output
mFilterIdToEvent[filterEvent.filterId] = filterEvent;
- startFilterEventThread(filterEvent);
+ readFilterEventData(filterEvent.filterId);
+ mPidFilterOutputCount++;
+ // mFilterIdToMQ.erase(filterEvent.filterId);
+
+ // startFilterEventThread(filterEvent);
mMsgCondition.signal();
return Void();
}
@@ -232,13 +236,16 @@
virtual Return<void> onInputStatus(DemuxInputStatus status) override {
// android::Mutex::Autolock autoLock(mMsgLock);
+ ALOGW("[vts] input status %d", status);
switch (status) {
case DemuxInputStatus::SPACE_EMPTY:
case DemuxInputStatus::SPACE_ALMOST_EMPTY:
+ ALOGW("[vts] keep inputing %d", status);
mKeepWritingInputFMQ = true;
break;
case DemuxInputStatus::SPACE_ALMOST_FULL:
case DemuxInputStatus::SPACE_FULL:
+ ALOGW("[vts] stop inputing %d", status);
mKeepWritingInputFMQ = false;
break;
}
@@ -246,78 +253,64 @@
}
void testOnFilterEvent(uint32_t filterId);
- void testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId, MQDesc& filterMQDescriptor,
- MQDesc& inputMQDescriptor);
void testFilterDataOutput();
- // Legacy
- bool readAndCompareSectionEventData(uint32_t filterId);
+ void stopInputThread();
void startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor);
void startFilterEventThread(DemuxFilterEvent event);
static void* __threadLoopInput(void* threadArgs);
static void* __threadLoopFilter(void* threadArgs);
- void inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ, MQDesc& inputMQDescriptor);
+ void inputThreadLoop(InputConf* inputConf, bool* keepWritingInputFMQ);
void filterThreadLoop(DemuxFilterEvent& event);
void updateFilterMQ(uint32_t filterId, MQDesc& filterMQDescriptor);
void updateGoldenOutputMap(uint32_t filterId, string goldenOutputFile);
+ bool readFilterEventData(uint32_t filterId);
private:
struct InputThreadArgs {
DemuxCallback* user;
- InputConf inputConf;
+ InputConf* inputConf;
bool* keepWritingInputFMQ;
- MQDesc& inputMQDesc;
};
struct FilterThreadArgs {
DemuxCallback* user;
- DemuxFilterEvent& event;
+ DemuxFilterEvent event;
};
uint16_t mDataLength = 0;
std::vector<uint8_t> mDataOutputBuffer;
bool mFilterEventReceived;
std::map<uint32_t, string> mFilterIdToGoldenOutput;
- std::map<uint32_t, DemuxFilterEvent> mFilterIdToEvent;
std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterIdToMQ;
std::unique_ptr<FilterMQ> mInputMQ;
std::map<uint32_t, EventFlag*> mFilterIdToMQEventFlag;
+ std::map<uint32_t, DemuxFilterEvent> mFilterIdToEvent;
EventFlag* mInputMQEventFlag;
android::Mutex mMsgLock;
android::Mutex mFilterOutputLock;
+ android::Mutex mInputThreadLock;
android::Condition mMsgCondition;
android::Condition mFilterOutputCondition;
- bool mKeepWritingInputFMQ;
+ bool mKeepWritingInputFMQ = true;
bool mInputThreadRunning;
pthread_t mInputThread;
pthread_t mFilterThread;
+
+ int mPidFilterOutputCount = 0;
};
-// Legacy
-void DemuxCallback::testOnFilterEvent(uint32_t filterId) {
- android::Mutex::Autolock autoLock(mMsgLock);
- while (!mFilterEventReceived) {
- if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "filter event not received within timeout";
- return;
- }
- }
- // Reset the filter event recieved flag
- mFilterEventReceived = false;
- // Check if filter id match
- EXPECT_TRUE(filterId == mFilterIdToEvent[filterId].filterId) << "filter id match";
-}
-
void DemuxCallback::startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor) {
+ mInputMQ = std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
+ EXPECT_TRUE(mInputMQ);
struct InputThreadArgs* threadArgs =
(struct InputThreadArgs*)malloc(sizeof(struct InputThreadArgs));
threadArgs->user = this;
- threadArgs->inputConf = inputConf;
+ threadArgs->inputConf = &inputConf;
threadArgs->keepWritingInputFMQ = &mKeepWritingInputFMQ;
- threadArgs->inputMQDesc = inputMQDescriptor;
pthread_create(&mInputThread, NULL, __threadLoopInput, (void*)threadArgs);
pthread_setname_np(mInputThread, "test_playback_input_loop");
@@ -334,72 +327,22 @@
}
void DemuxCallback::testFilterDataOutput() {
- android::Mutex::Autolock autoLock(mFilterOutputLock);
- while (!mFilterIdToMQ.empty()) {
- if (-ETIMEDOUT == mFilterOutputCondition.waitRelative(mFilterOutputLock, WAIT_TIMEOUT)) {
- EXPECT_TRUE(false) << "filter output does not match golden output within timeout";
+ android::Mutex::Autolock autoLock(mMsgLock);
+ while (mPidFilterOutputCount < 1) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
return;
}
}
+ mPidFilterOutputCount = 0;
+ ALOGW("[vts] pass and stop");
}
-// Legacy
-void DemuxCallback::testOnSectionFilterEvent(sp<IDemux>& demux, uint32_t filterId,
- MQDesc& filterMQDescriptor,
- MQDesc& inputMQDescriptor) {
- Result status;
- // Create MQ to read the output into the local buffer
- mFilterIdToMQ[filterId] =
- std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mFilterIdToMQ[filterId]);
- // Get the MQ to write the input to the HAL
- mInputMQ = std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(mInputMQ);
- // Create the EventFlag that is used to signal the HAL impl that data have been
- // read the Filter FMQ
- EXPECT_TRUE(EventFlag::createEventFlag(mFilterIdToMQ[filterId]->getEventFlagWord(),
- &mFilterIdToMQEventFlag[filterId]) == android::OK);
- // Create the EventFlag that is used to signal the HAL impl that data have been
- // written into the Input FMQ
- EXPECT_TRUE(EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputMQEventFlag) ==
- android::OK);
- // Start filter
- status = demux->startFilter(filterId);
- status = demux->startInput();
+void DemuxCallback::stopInputThread() {
+ mInputThreadRunning = false;
+ mKeepWritingInputFMQ = false;
- EXPECT_EQ(status, Result::SUCCESS);
- // Test start filter and receive callback event
- for (int i = 0; i < SECTION_READ_COUNT; i++) {
- // Write input FMQ and notify the Tuner Implementation
- EXPECT_TRUE(mInputMQ->write(goldenDataOutputBuffer.data(), goldenDataOutputBuffer.size()));
- mInputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
- testOnFilterEvent(filterId);
- // checksum of mDataOutputBuffer and Input golden input
- if (readAndCompareSectionEventData(filterId) && i < SECTION_READ_COUNT - 1) {
- mFilterIdToMQEventFlag[filterId]->wake(
- static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
- }
- }
-}
-
-// Legacy
-bool DemuxCallback::readAndCompareSectionEventData(uint32_t filterId) {
- bool result = false;
- DemuxFilterEvent filterEvent = mFilterIdToEvent[filterId];
- for (int i = 0; i < filterEvent.events.size(); i++) {
- DemuxFilterSectionEvent event = filterEvent.events[i].section();
- mDataLength = event.dataLength;
- EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not match";
-
- mDataOutputBuffer.resize(mDataLength);
- result = mFilterIdToMQ[filterId]->read(mDataOutputBuffer.data(), mDataLength);
- EXPECT_TRUE(result) << "can't read from Filter MQ";
-
- for (int i = 0; i < mDataLength; i++) {
- EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
- }
- }
- return result;
+ android::Mutex::Autolock autoLock(mInputThreadLock);
}
void DemuxCallback::updateFilterMQ(uint32_t filterId, MQDesc& filterMQDescriptor) {
@@ -418,58 +361,60 @@
DemuxCallback* const self =
static_cast<DemuxCallback*>(((struct InputThreadArgs*)threadArgs)->user);
self->inputThreadLoop(((struct InputThreadArgs*)threadArgs)->inputConf,
- ((struct InputThreadArgs*)threadArgs)->keepWritingInputFMQ,
- ((struct InputThreadArgs*)threadArgs)->inputMQDesc);
+ ((struct InputThreadArgs*)threadArgs)->keepWritingInputFMQ);
return 0;
}
-void DemuxCallback::inputThreadLoop(InputConf inputConf, bool* keepWritingInputFMQ,
- MQDesc& inputMQDescriptor) {
+void DemuxCallback::inputThreadLoop(InputConf* inputConf, bool* keepWritingInputFMQ) {
+ android::Mutex::Autolock autoLock(mInputThreadLock);
mInputThreadRunning = true;
- std::unique_ptr inputMQ =
- std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
- EXPECT_TRUE(inputMQ);
-
// Create the EventFlag that is used to signal the HAL impl that data have been
// written into the Input FMQ
EventFlag* inputMQEventFlag;
- EXPECT_TRUE(EventFlag::createEventFlag(inputMQ->getEventFlagWord(), &inputMQEventFlag) ==
+ EXPECT_TRUE(EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &inputMQEventFlag) ==
android::OK);
// open the stream and get its length
- std::ifstream inputData(inputConf.inputDataFile /*"ts/test1.ts"*/, std::ifstream::binary);
- int writeSize = inputConf.setting.packetSize * 6;
+ std::ifstream inputData(inputConf->inputDataFile, std::ifstream::binary);
+ int writeSize = inputConf->setting.packetSize * 6;
char* buffer = new char[writeSize];
- if (!inputData) {
- // log
+ ALOGW("[vts] input thread loop start %s", inputConf->inputDataFile.c_str());
+ if (!inputData.is_open()) {
mInputThreadRunning = false;
+ ALOGW("[vts] Error %s", strerror(errno));
}
while (mInputThreadRunning) {
- // move the stream pointer for packet size * 2k? every read until end
+ // move the stream pointer for packet size * 6 every read until the end
while (*keepWritingInputFMQ) {
inputData.read(buffer, writeSize);
if (!inputData) {
int leftSize = inputData.gcount();
+ if (leftSize == 0) {
+ mInputThreadRunning = false;
+ break;
+ }
inputData.clear();
inputData.read(buffer, leftSize);
// Write the left over of the input data and quit the thread
if (leftSize > 0) {
- EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0],
- leftSize / inputConf.setting.packetSize));
+ EXPECT_TRUE(mInputMQ->write((unsigned char*)&buffer[0], leftSize));
inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
}
mInputThreadRunning = false;
break;
}
// Write input FMQ and notify the Tuner Implementation
- EXPECT_TRUE(inputMQ->write((unsigned char*)&buffer[0], 6));
+ EXPECT_TRUE(mInputMQ->write((unsigned char*)&buffer[0], writeSize));
inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
inputData.seekg(writeSize, inputData.cur);
+ sleep(1);
}
}
+ ALOGW("[vts] Input thread end.");
+
delete[] buffer;
inputData.close();
}
@@ -481,9 +426,9 @@
return 0;
}
-void DemuxCallback::filterThreadLoop(DemuxFilterEvent& /*event*/) {
+void DemuxCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
android::Mutex::Autolock autoLock(mFilterOutputLock);
- // Read from MQ[event.filterId] per event and filter type
+ // Read from mFilterIdToMQ[event.filterId] per event and filter type
// Assemble to filterOutput[filterId]
@@ -494,6 +439,30 @@
// end thread
}
+bool DemuxCallback::readFilterEventData(uint32_t filterId) {
+ bool result = false;
+ DemuxFilterEvent filterEvent = mFilterIdToEvent[filterId];
+ ALOGW("[vts] reading from filter FMQ %d", filterId);
+ // todo separate filter handlers
+ for (int i = 0; i < filterEvent.events.size(); i++) {
+ DemuxFilterPesEvent event = filterEvent.events[i].pes();
+ mDataLength = event.dataLength;
+ // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
+ // match";
+
+ mDataOutputBuffer.resize(mDataLength);
+ result = mFilterIdToMQ[filterId]->read(mDataOutputBuffer.data(), mDataLength);
+ EXPECT_TRUE(result) << "can't read from Filter MQ";
+
+ /*for (int i = 0; i < mDataLength; i++) {
+ EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
+ }*/
+ }
+ mFilterIdToMQEventFlag[filterId]->wake(
+ static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+ return result;
+}
+
// Test environment for Tuner HIDL HAL.
class TunerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
public:
@@ -528,6 +497,7 @@
sp<DemuxCallback> mDemuxCallback;
MQDesc mFilterMQDescriptor;
MQDesc mInputMQDescriptor;
+ vector<uint32_t> mUsedFilterIds;
uint32_t mDemuxId;
uint32_t mFilterId;
@@ -540,7 +510,8 @@
::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
::testing::AssertionResult closeFrontend(int32_t frontendId);
::testing::AssertionResult createDemux();
- ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId);
+ ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId,
+ FrontendSettings settings);
::testing::AssertionResult getInputMQDescriptor();
::testing::AssertionResult addInputToDemux(DemuxInputSettings setting);
::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting);
@@ -552,10 +523,8 @@
::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf,
InputConf inputConf,
vector<string> goldenOutputFiles);
-
- // Legacy
- ::testing::AssertionResult addSectionFilterToDemux();
- ::testing::AssertionResult readSectionFilterDataOutput();
+ ::testing::AssertionResult broadcastDataFlowTest(vector<FilterConf> filterConf,
+ vector<string> goldenOutputFiles);
};
::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
@@ -586,7 +555,7 @@
.frequency = 0,
.modulation = FrontendAtscModulation::UNDEFINED,
};
- frontendSettings.atsc() = frontendAtscSettings;
+ frontendSettings.atsc(frontendAtscSettings);
mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
FrontendDvbtSettings frontendDvbtSettings{
@@ -630,7 +599,8 @@
return ::testing::AssertionResult(status == Result::SUCCESS);
}
-::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId) {
+::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId,
+ FrontendSettings settings) {
Result status;
if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
@@ -641,6 +611,8 @@
return ::testing::AssertionFailure();
}
+ mFrontendCallback->testOnEvent(mFrontend, settings);
+
status = mDemux->setFrontendDataSource(frontendId);
return ::testing::AssertionResult(status == Result::SUCCESS);
@@ -705,7 +677,7 @@
mDemuxCallback = new DemuxCallback();
}
- // Add section filter to the local demux
+ // Add playback input to the local demux
status = mDemux->addInput(FMQ_SIZE_1M, mDemuxCallback);
if (status != Result::SUCCESS) {
@@ -732,29 +704,6 @@
return ::testing::AssertionResult(status == Result::SUCCESS);
}
-// Legacy
-::testing::AssertionResult TunerHidlTest::addSectionFilterToDemux() {
- Result status;
-
- if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Create demux callback
- if (!mDemuxCallback) {
- mDemuxCallback = new DemuxCallback();
- }
-
- // Add section filter to the local demux
- mDemux->addFilter(DemuxFilterType::SECTION, FMQ_SIZE_4K, mDemuxCallback,
- [&](Result result, uint32_t filterId) {
- mFilterId = filterId;
- status = result;
- });
-
- return ::testing::AssertionResult(status == Result::SUCCESS);
-}
-
::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type,
DemuxFilterSettings setting) {
Result status;
@@ -800,36 +749,10 @@
return ::testing::AssertionResult(status == Result::SUCCESS);
}
-// Legacy
-::testing::AssertionResult TunerHidlTest::readSectionFilterDataOutput() {
- // Filter Configuration Module
- DemuxInputSettings setting{
- .statusMask = 0xf,
- .lowThreshold = 0x1000,
- .highThreshold = 0x100000,
- .dataFormat = DemuxDataFormat::TS,
- .packetSize = 188,
- };
- if (addSectionFilterToDemux() == ::testing::AssertionFailure() ||
- getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure() ||
- addInputToDemux(setting) == ::testing::AssertionFailure() ||
- getInputMQDescriptor() == ::testing::AssertionFailure()) {
- return ::testing::AssertionFailure();
- }
-
- // Data Verify Module
- // Test start filter and read the output data
- mDemuxCallback->testOnSectionFilterEvent(mDemux, mFilterId, mFilterMQDescriptor,
- mInputMQDescriptor);
-
- // Clean Up Module
- return closeDemux(); //::testing::AssertionSuccess();
-}
-
-::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(vector<FilterConf> filterConf,
- InputConf inputConf,
- vector<string> goldenOutputFiles) {
+::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(
+ vector<FilterConf> filterConf, InputConf inputConf, vector<string> /*goldenOutputFiles*/) {
Result status;
+ int filterIdsSize;
// Filter Configuration Module
for (int i = 0; i < filterConf.size(); i++) {
if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
@@ -838,8 +761,11 @@
getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) {
return ::testing::AssertionFailure();
}
+ filterIdsSize = mUsedFilterIds.size();
+ mUsedFilterIds.resize(filterIdsSize + 1);
+ mUsedFilterIds[filterIdsSize] = mFilterId;
mDemuxCallback->updateFilterMQ(mFilterId, mFilterMQDescriptor);
- mDemuxCallback->updateGoldenOutputMap(mFilterId, goldenOutputFiles[i]);
+ // mDemuxCallback->updateGoldenOutputMap(mFilterId, goldenOutputFiles[i]);
status = mDemux->startFilter(mFilterId);
if (status != Result::SUCCESS) {
return ::testing::AssertionFailure();
@@ -860,8 +786,76 @@
// Data Verify Module
mDemuxCallback->testFilterDataOutput();
+ mDemuxCallback->stopInputThread();
// Clean Up Module
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mDemux->stopFilter(mUsedFilterIds[i]) != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+ }
+ if (mDemux->stopInput() != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+ return closeDemux();
+}
+
+::testing::AssertionResult TunerHidlTest::broadcastDataFlowTest(
+ vector<FilterConf> filterConf, vector<string> /*goldenOutputFiles*/) {
+ Result status;
+ hidl_vec<FrontendId> feIds;
+
+ mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+ status = result;
+ feIds = frontendIds;
+ });
+
+ if (feIds.size() == 0) {
+ ALOGW("[ WARN ] Frontend isn't available");
+ return ::testing::AssertionFailure();
+ }
+
+ FrontendDvbtSettings dvbt{
+ .frequency = 1000,
+ };
+ FrontendSettings settings;
+ settings.dvbt(dvbt);
+
+ if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
+ return ::testing::AssertionFailure();
+ }
+
+ int filterIdsSize;
+ // Filter Configuration Module
+ for (int i = 0; i < filterConf.size(); i++) {
+ if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+ ::testing::AssertionFailure() ||
+ // TODO use a map to save the FMQs/EvenFlags and pass to callback
+ getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) {
+ return ::testing::AssertionFailure();
+ }
+ filterIdsSize = mUsedFilterIds.size();
+ mUsedFilterIds.resize(filterIdsSize + 1);
+ mUsedFilterIds[filterIdsSize] = mFilterId;
+ mDemuxCallback->updateFilterMQ(mFilterId, mFilterMQDescriptor);
+ status = mDemux->startFilter(mFilterId);
+ if (status != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+ }
+
+ // Data Verify Module
+ mDemuxCallback->testFilterDataOutput();
+
+ // Clean Up Module
+ for (int i = 0; i <= filterIdsSize; i++) {
+ if (mDemux->stopFilter(mUsedFilterIds[i]) != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
+ }
+ if (mFrontend->stopTune() != Result::SUCCESS) {
+ return ::testing::AssertionFailure();
+ }
return closeDemux();
}
@@ -948,7 +942,7 @@
}
}
-TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
+/*TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
Result status;
hidl_vec<FrontendId> feIds;
@@ -963,10 +957,17 @@
return;
}
+ FrontendDvbtSettings dvbt{
+ .frequency = 1000,
+ };
+ FrontendSettings settings;
+ settings.dvbt(dvbt);
+
for (size_t i = 0; i < feIds.size(); i++) {
- ASSERT_TRUE(createDemuxWithFrontend(feIds[i]));
+ ASSERT_TRUE(createDemuxWithFrontend(feIds[i], settings));
+ mFrontend->stopTune();
}
-}
+}*/
TEST_F(TunerHidlTest, CreateDemux) {
description("Create Demux");
@@ -991,9 +992,63 @@
/*
* DATA FLOW TESTS
*/
-TEST_F(TunerHidlTest, ReadSectionFilterOutput) {
- description("Read data output from FMQ of a Section Filter");
- ASSERT_TRUE(readSectionFilterDataOutput());
+TEST_F(TunerHidlTest, PlaybackDataFlowWithPesFilterTest) {
+ description("Feed ts data from playback and configure pes filter to get output");
+
+ // todo modulize the filter conf parser
+ vector<FilterConf> filterConf;
+ filterConf.resize(1);
+
+ DemuxFilterSettings filterSetting;
+ DemuxFilterPesDataSettings pesFilterSetting{
+ .tpid = 18,
+ };
+ filterSetting.pesData(pesFilterSetting);
+ FilterConf pesFilterConf{
+ .type = DemuxFilterType::PES,
+ .setting = filterSetting,
+ };
+ filterConf[0] = pesFilterConf;
+
+ DemuxInputSettings inputSetting{
+ .statusMask = 0xf,
+ .lowThreshold = 0x1000,
+ .highThreshold = 0x07fff,
+ .dataFormat = DemuxDataFormat::TS,
+ .packetSize = 188,
+ };
+
+ InputConf inputConf{
+ .inputDataFile = "/vendor/etc/test1.ts",
+ .setting = inputSetting,
+ };
+
+ vector<string> goldenOutputFiles;
+
+ ASSERT_TRUE(playbackDataFlowTest(filterConf, inputConf, goldenOutputFiles));
+}
+
+TEST_F(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
+ description("Feed ts data from frontend and test with PES filter");
+
+ // todo modulize the filter conf parser
+ vector<FilterConf> filterConf;
+ filterConf.resize(1);
+
+ DemuxFilterSettings filterSetting;
+ DemuxFilterPesDataSettings pesFilterSetting{
+ .tpid = 18,
+ };
+ filterSetting.pesData(pesFilterSetting);
+ FilterConf pesFilterConf{
+ .type = DemuxFilterType::PES,
+ .setting = filterSetting,
+ };
+ filterConf[0] = pesFilterConf;
+
+ vector<string> goldenOutputFiles;
+
+ ASSERT_TRUE(broadcastDataFlowTest(filterConf, goldenOutputFiles));
}
} // namespace
diff --git a/vibrator/1.4/Android.bp b/vibrator/1.4/Android.bp
new file mode 100644
index 0000000..cf31fcd
--- /dev/null
+++ b/vibrator/1.4/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.vibrator@1.4",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "types.hal",
+ "IVibrator.hal",
+ "IVibratorCallback.hal",
+ ],
+ interfaces: [
+ "android.hardware.vibrator@1.0",
+ "android.hardware.vibrator@1.1",
+ "android.hardware.vibrator@1.2",
+ "android.hardware.vibrator@1.3",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: true,
+}
diff --git a/vibrator/1.4/IVibrator.hal b/vibrator/1.4/IVibrator.hal
new file mode 100644
index 0000000..913abe3
--- /dev/null
+++ b/vibrator/1.4/IVibrator.hal
@@ -0,0 +1,57 @@
+/*
+ * 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.vibrator@1.4;
+
+import @1.0::EffectStrength;
+import @1.3::Effect;
+import @1.0::Status;
+import @1.3::IVibrator;
+import IVibratorCallback;
+
+interface IVibrator extends @1.3::IVibrator {
+ /**
+ * Determine capabilities of the vibrator HAL.
+ */
+ getCapabilities() generates (bitfield<Capabilities> capabilities);
+
+ /**
+ * Turn on vibrator
+ *
+ * This function must only be called after the previous timeout has expired or
+ * was canceled (through off()).
+ * @param timeoutMs number of milliseconds to vibrate.
+ * @param callback A callback used to inform Frameworks of state change, if supported.
+ * @return vibratorOnRet whether vibrator command was successful or not.
+ */
+ on_1_4(uint32_t timeoutMs, IVibratorCallback callback) generates (Status vibratorOnRet);
+
+ /**
+ * Fire off a predefined haptic event.
+ *
+ * @param effect The type of haptic event to trigger.
+ * @param strength The intensity of haptic event to trigger.
+ * @param callback A callback used to inform Frameworks of state change, if supported.
+ * @return status Whether the effect was successfully performed or not. Must
+ * return Status::UNSUPPORTED_OPERATION if the effect is not supported.
+ * @return lengthMs The length of time the event is expected to take in
+ * milliseconds. This doesn't need to be perfectly accurate, but should be a reasonable
+ * approximation. Should be a positive, non-zero value if the returned status is Status::OK,
+ * and set to 0 otherwise.
+ */
+ perform_1_4(Effect effect, EffectStrength strength, IVibratorCallback callback)
+ generates (Status status, uint32_t lengthMs);
+};
diff --git a/vibrator/1.4/IVibratorCallback.hal b/vibrator/1.4/IVibratorCallback.hal
new file mode 100644
index 0000000..76281bc
--- /dev/null
+++ b/vibrator/1.4/IVibratorCallback.hal
@@ -0,0 +1,21 @@
+/*
+ * 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.vibrator@1.4;
+
+interface IVibratorCallback {
+ oneway onComplete();
+};
diff --git a/vibrator/1.4/types.hal b/vibrator/1.4/types.hal
new file mode 100644
index 0000000..acc49b1
--- /dev/null
+++ b/vibrator/1.4/types.hal
@@ -0,0 +1,22 @@
+/*
+ * 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.vibrator@1.4;
+
+enum Capabilities : uint32_t {
+ ON_COMPLETION_CALLBACK = 1 << 0,
+ PERFORM_COMPLETION_CALLBACK = 1 << 1,
+};