Merge "HidlUtils: remove temporary conversion functions"
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
index 65b75e5..2e00fce 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Callbacks.h
@@ -27,6 +27,9 @@
 #include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
 class PreparedModelCallback final : public IPreparedModelCallback,
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
index ee103ba..db3b2ad 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Device.h
@@ -32,8 +32,12 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
+// Class that adapts V1_0::IDevice to nn::IDevice.
 class Device final : public nn::IDevice {
     struct PrivateConstructorTag {};
 
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
index 31f366d..2de1828 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/PreparedModel.h
@@ -29,8 +29,12 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
+// Class that adapts V1_0::IPreparedModel to nn::IPreparedModel.
 class PreparedModel final : public nn::IPreparedModel {
     struct PrivateConstructorTag {};
 
@@ -44,13 +48,13 @@
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
             const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
     std::any getUnderlyingResource() const override;
 
diff --git a/neuralnetworks/1.0/utils/src/Callbacks.cpp b/neuralnetworks/1.0/utils/src/Callbacks.cpp
index b1259c3..a0bdb3c 100644
--- a/neuralnetworks/1.0/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.0/utils/src/Callbacks.cpp
@@ -32,6 +32,9 @@
 
 #include <utility>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 namespace {
 
diff --git a/neuralnetworks/1.0/utils/src/Device.cpp b/neuralnetworks/1.0/utils/src/Device.cpp
index 285c515..83e0015 100644
--- a/neuralnetworks/1.0/utils/src/Device.cpp
+++ b/neuralnetworks/1.0/utils/src/Device.cpp
@@ -38,6 +38,9 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 namespace {
 
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index 46dd3f8..c1dd1d9 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -34,6 +34,9 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_0::utils {
 
 nn::GeneralResult<std::shared_ptr<const PreparedModel>> PreparedModel::create(
@@ -55,7 +58,7 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming /*measure*/,
         const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
@@ -81,11 +84,12 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(
-        const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
-        nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
-        const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(const nn::Request& /*request*/,
+                             const std::vector<nn::SyncFence>& /*waitFor*/,
+                             nn::MeasureTiming /*measure*/,
+                             const nn::OptionalTimePoint& /*deadline*/,
+                             const nn::OptionalDuration& /*loopTimeoutDuration*/,
+                             const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "IPreparedModel::executeFenced is not supported on 1.0 HAL service";
 }
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
index c1e95fe1a..5e224b5 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Device.h
@@ -32,8 +32,12 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_1::utils {
 
+// Class that adapts V1_1::IDevice to nn::IDevice.
 class Device final : public nn::IDevice {
     struct PrivateConstructorTag {};
 
diff --git a/neuralnetworks/1.1/utils/src/Device.cpp b/neuralnetworks/1.1/utils/src/Device.cpp
index f73d3f8..b57c7f4 100644
--- a/neuralnetworks/1.1/utils/src/Device.cpp
+++ b/neuralnetworks/1.1/utils/src/Device.cpp
@@ -39,6 +39,9 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_1::utils {
 namespace {
 
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
index bc7d92a..1162bc3 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Callbacks.h
@@ -31,6 +31,9 @@
 #include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 
 class PreparedModelCallback final : public IPreparedModelCallback,
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index a68830d..79c3b04 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -32,6 +32,9 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 
 nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device);
@@ -40,6 +43,7 @@
 nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
         V1_2::IDevice* device);
 
+// Class that adapts V1_2::IDevice to nn::IDevice.
 class Device final : public nn::IDevice {
     struct PrivateConstructorTag {};
 
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
index 65e1e8a..8ed5ca7 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/PreparedModel.h
@@ -30,8 +30,12 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 
+// Class that adapts V1_2::IPreparedModel to nn::IPreparedModel.
 class PreparedModel final : public nn::IPreparedModel {
     struct PrivateConstructorTag {};
 
@@ -45,13 +49,13 @@
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
             const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
     std::any getUnderlyingResource() const override;
 
diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp
index 39f88c2..ab3e0ca 100644
--- a/neuralnetworks/1.2/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp
@@ -36,6 +36,9 @@
 
 #include <utility>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 namespace {
 
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index f11474f..3790d1f 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -43,7 +43,9 @@
     return static_cast<std::underlying_type_t<Type>>(value);
 }
 
+using HalDuration = std::chrono::duration<uint64_t, std::micro>;
 constexpr auto kVersion = android::nn::Version::ANDROID_Q;
+constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
 
 }  // namespace
 
@@ -270,7 +272,18 @@
 }
 
 GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
-    return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+    constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
+    constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
+        if (halTiming == kNoTiming) {
+            return {};
+        }
+        if (halTiming > kMaxTiming) {
+            return Duration::max();
+        }
+        return HalDuration{halTiming};
+    };
+    return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
+                  .timeInDriver = convertTiming(timing.timeInDriver)};
 }
 
 GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
@@ -547,7 +560,14 @@
 }
 
 nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
-    return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
+    constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
+        if (!canonicalTiming.has_value()) {
+            return kNoTiming;
+        }
+        return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
+    };
+    return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
+                  .timeInDriver = convertTiming(timing.timeInDriver)};
 }
 
 nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 0061065..6cca841 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -41,6 +41,9 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 namespace {
 
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index dad9a7e..b422ced 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -37,6 +37,9 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_2::utils {
 namespace {
 
@@ -106,7 +109,7 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming measure,
         const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
@@ -140,11 +143,12 @@
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-PreparedModel::executeFenced(
-        const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
-        nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
-        const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+PreparedModel::executeFenced(const nn::Request& /*request*/,
+                             const std::vector<nn::SyncFence>& /*waitFor*/,
+                             nn::MeasureTiming /*measure*/,
+                             const nn::OptionalTimePoint& /*deadline*/,
+                             const nn::OptionalDuration& /*loopTimeoutDuration*/,
+                             const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "IPreparedModel::executeFenced is not supported on 1.2 HAL service";
 }
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h
index 637179d..fda79c8 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Buffer.h
@@ -24,8 +24,12 @@
 #include <nnapi/Types.h>
 #include <memory>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
+// Class that adapts V1_3::IBuffer to nn::IBuffer.
 class Buffer final : public nn::IBuffer {
     struct PrivateConstructorTag {};
 
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
index d46b111..cb2a56a 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Callbacks.h
@@ -34,6 +34,9 @@
 #include <nnapi/hal/ProtectCallback.h>
 #include <nnapi/hal/TransferValue.h>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
 class PreparedModelCallback final : public IPreparedModelCallback,
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
index 9653a05..477bb7b 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Conversions.h
@@ -44,7 +44,7 @@
         const hal::V1_3::Request::MemoryPool& memoryPool);
 GeneralResult<OptionalTimePoint> unvalidatedConvert(
         const hal::V1_3::OptionalTimePoint& optionalTimePoint);
-GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
+GeneralResult<OptionalDuration> unvalidatedConvert(
         const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration);
 GeneralResult<ErrorStatus> unvalidatedConvert(const hal::V1_3::ErrorStatus& errorStatus);
 
@@ -54,7 +54,7 @@
 GeneralResult<BufferDesc> convert(const hal::V1_3::BufferDesc& bufferDesc);
 GeneralResult<Request> convert(const hal::V1_3::Request& request);
 GeneralResult<OptionalTimePoint> convert(const hal::V1_3::OptionalTimePoint& optionalTimePoint);
-GeneralResult<OptionalTimeoutDuration> convert(
+GeneralResult<OptionalDuration> convert(
         const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration);
 GeneralResult<ErrorStatus> convert(const hal::V1_3::ErrorStatus& errorStatus);
 
@@ -86,7 +86,7 @@
 nn::GeneralResult<OptionalTimePoint> unvalidatedConvert(
         const nn::OptionalTimePoint& optionalTimePoint);
 nn::GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
-        const nn::OptionalTimeoutDuration& optionalTimeoutDuration);
+        const nn::OptionalDuration& optionalTimeoutDuration);
 nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus);
 
 nn::GeneralResult<Priority> convert(const nn::Priority& priority);
@@ -96,7 +96,7 @@
 nn::GeneralResult<Request> convert(const nn::Request& request);
 nn::GeneralResult<OptionalTimePoint> convert(const nn::OptionalTimePoint& optionalTimePoint);
 nn::GeneralResult<OptionalTimeoutDuration> convert(
-        const nn::OptionalTimeoutDuration& optionalTimeoutDuration);
+        const nn::OptionalDuration& optionalTimeoutDuration);
 nn::GeneralResult<ErrorStatus> convert(const nn::ErrorStatus& errorStatus);
 
 nn::GeneralResult<hidl_handle> convert(const nn::SharedHandle& handle);
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
index 0f5234b..84f606a 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Device.h
@@ -32,8 +32,12 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
+// Class that adapts V1_3::IDevice to nn::IDevice.
 class Device final : public nn::IDevice {
     struct PrivateConstructorTag {};
 
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
index e0d69dd..c4ba483 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/PreparedModel.h
@@ -29,8 +29,12 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
+// Class that adapts V1_3::IPreparedModel to nn::IPreparedModel.
 class PreparedModel final : public nn::IPreparedModel {
     struct PrivateConstructorTag {};
 
@@ -44,13 +48,13 @@
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
             const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
     std::any getUnderlyingResource() const override;
 
diff --git a/neuralnetworks/1.3/utils/src/Buffer.cpp b/neuralnetworks/1.3/utils/src/Buffer.cpp
index ffdeccd..4ef54a2 100644
--- a/neuralnetworks/1.3/utils/src/Buffer.cpp
+++ b/neuralnetworks/1.3/utils/src/Buffer.cpp
@@ -33,6 +33,9 @@
 #include <memory>
 #include <utility>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 
 nn::GeneralResult<std::shared_ptr<const Buffer>> Buffer::create(
diff --git a/neuralnetworks/1.3/utils/src/Callbacks.cpp b/neuralnetworks/1.3/utils/src/Callbacks.cpp
index e3c6074..17c20fb 100644
--- a/neuralnetworks/1.3/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.3/utils/src/Callbacks.cpp
@@ -39,6 +39,9 @@
 
 #include <utility>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 namespace {
 
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index 949dd0d..c89a69f 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -272,47 +272,26 @@
 
 GeneralResult<OptionalTimePoint> unvalidatedConvert(
         const hal::V1_3::OptionalTimePoint& optionalTimePoint) {
-    constexpr auto kTimePointMaxCount = TimePoint::max().time_since_epoch().count();
-    const auto makeTimePoint = [](uint64_t count) -> GeneralResult<OptionalTimePoint> {
-        if (count > kTimePointMaxCount) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-                   << "Unable to unvalidatedConvert OptionalTimePoint because the count exceeds "
-                      "the max";
-        }
-        const auto nanoseconds = std::chrono::nanoseconds{count};
-        return TimePoint{nanoseconds};
-    };
-
     using Discriminator = hal::V1_3::OptionalTimePoint::hidl_discriminator;
     switch (optionalTimePoint.getDiscriminator()) {
         case Discriminator::none:
-            return std::nullopt;
+            return {};
         case Discriminator::nanosecondsSinceEpoch:
-            return makeTimePoint(optionalTimePoint.nanosecondsSinceEpoch());
+            return TimePoint{Duration{optionalTimePoint.nanosecondsSinceEpoch()}};
     }
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "Invalid OptionalTimePoint discriminator "
            << underlyingType(optionalTimePoint.getDiscriminator());
 }
 
-GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
+GeneralResult<OptionalDuration> unvalidatedConvert(
         const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
-    constexpr auto kTimeoutDurationMaxCount = TimeoutDuration::max().count();
-    const auto makeTimeoutDuration = [](uint64_t count) -> GeneralResult<OptionalTimeoutDuration> {
-        if (count > kTimeoutDurationMaxCount) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-                   << "Unable to unvalidatedConvert OptionalTimeoutDuration because the count "
-                      "exceeds the max";
-        }
-        return TimeoutDuration{count};
-    };
-
     using Discriminator = hal::V1_3::OptionalTimeoutDuration::hidl_discriminator;
     switch (optionalTimeoutDuration.getDiscriminator()) {
         case Discriminator::none:
-            return std::nullopt;
+            return {};
         case Discriminator::nanoseconds:
-            return makeTimeoutDuration(optionalTimeoutDuration.nanoseconds());
+            return Duration(optionalTimeoutDuration.nanoseconds());
     }
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "Invalid OptionalTimeoutDuration discriminator "
@@ -360,7 +339,7 @@
     return validatedConvert(optionalTimePoint);
 }
 
-GeneralResult<OptionalTimeoutDuration> convert(
+GeneralResult<OptionalDuration> convert(
         const hal::V1_3::OptionalTimeoutDuration& optionalTimeoutDuration) {
     return validatedConvert(optionalTimeoutDuration);
 }
@@ -629,27 +608,16 @@
     OptionalTimePoint ret;
     if (optionalTimePoint.has_value()) {
         const auto count = optionalTimePoint.value().time_since_epoch().count();
-        if (count < 0) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-                   << "Unable to unvalidatedConvert OptionalTimePoint because time since epoch "
-                      "count is "
-                      "negative";
-        }
         ret.nanosecondsSinceEpoch(count);
     }
     return ret;
 }
 
 nn::GeneralResult<OptionalTimeoutDuration> unvalidatedConvert(
-        const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
+        const nn::OptionalDuration& optionalTimeoutDuration) {
     OptionalTimeoutDuration ret;
     if (optionalTimeoutDuration.has_value()) {
         const auto count = optionalTimeoutDuration.value().count();
-        if (count < 0) {
-            return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-                   << "Unable to unvalidatedConvert OptionalTimeoutDuration because count is "
-                      "negative";
-        }
         ret.nanoseconds(count);
     }
     return ret;
@@ -697,7 +665,7 @@
 }
 
 nn::GeneralResult<OptionalTimeoutDuration> convert(
-        const nn::OptionalTimeoutDuration& optionalTimeoutDuration) {
+        const nn::OptionalDuration& optionalTimeoutDuration) {
     return validatedConvert(optionalTimeoutDuration);
 }
 
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 82837ba..6056498 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -47,6 +47,9 @@
 #include <string>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 namespace {
 
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index 49b9b0b..0bae95d 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -39,6 +39,9 @@
 #include <utility>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::V1_3::utils {
 namespace {
 
@@ -159,7 +162,7 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> PreparedModel::execute(
         const nn::Request& request, nn::MeasureTiming measure,
         const nn::OptionalTimePoint& deadline,
-        const nn::OptionalTimeoutDuration& loopTimeoutDuration) const {
+        const nn::OptionalDuration& loopTimeoutDuration) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     const nn::Request& requestInShared = NN_TRY(hal::utils::makeExecutionFailure(
@@ -200,8 +203,8 @@
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
 PreparedModel::executeFenced(const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
                              nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-                             const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-                             const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const {
+                             const nn::OptionalDuration& loopTimeoutDuration,
+                             const nn::OptionalDuration& timeoutDurationAfterFence) const {
     // Ensure that request is ready for IPC.
     std::optional<nn::Request> maybeRequestInShared;
     const nn::Request& requestInShared =
diff --git a/neuralnetworks/utils/README.md b/neuralnetworks/utils/README.md
index 0dee103..45ca0b4 100644
--- a/neuralnetworks/utils/README.md
+++ b/neuralnetworks/utils/README.md
@@ -1,11 +1,11 @@
 # NNAPI Conversions
 
 `convert` fails if either the source type or the destination type is invalid, and it yields a valid
-object if the conversion succeeds. For example, let's say that an enumeration in the current
-version has fewer possible values than the "same" canonical enumeration, such as `OperationType`.
-The new value of `HARD_SWISH` (introduced in Android R / NN HAL 1.3) does not map to any valid
-existing value in `OperationType`, but an older value of `ADD` (introduced in Android OC-MR1 / NN
-HAL 1.0) is valid. This can be seen in the following model conversions:
+object if the conversion succeeds. For example, let's say that an enumeration in the current version
+has fewer possible values than the "same" canonical enumeration, such as `OperationType`. The new
+value of `HARD_SWISH` (introduced in Android R / NN HAL 1.3) does not map to any valid existing
+value in `OperationType`, but an older value of `ADD` (introduced in Android OC-MR1 / NN HAL 1.0) is
+valid. This can be seen in the following model conversions:
 
 ```cpp
 // Unsuccessful conversion
@@ -48,3 +48,50 @@
 `unvalidatedConvert` functions operate on types that are either used in a HIDL method call directly
 (i.e., not as a nested class) or used in a subsequent version of the NN HAL. Prefer using `convert`
 over `unvalidatedConvert`.
+
+# HIDL Interface Lifetimes across Processes
+
+Some notes about HIDL interface objects and lifetimes across processes:
+
+All HIDL interface objects inherit from `IBase`, which itself inherits from `::android::RefBase`. As
+such, all HIDL interface objects are reference counted and must be owned through `::android::sp` (or
+referenced through `::android::wp`). Allocating `RefBase` objects on the stack will log errors and
+may result in crashes, and deleting a `RefBase` object through another means (e.g., "delete",
+"free", or RAII-cleanup through `std::unique_ptr` or some equivalent) will result in double-free
+and/or use-after-free undefined behavior.
+
+HIDL/Binder manages the reference count of HIDL interface objects automatically across processes. If
+a process that references (but did not create) the HIDL interface object dies, HIDL/Binder ensures
+any reference count it held is properly released. (Caveat: it might be possible that HIDL/Binder
+behave strangely with `::android::wp` references.)
+
+If the process which created the HIDL interface object dies, any call on this object from another
+process will result in a HIDL transport error with the code `DEAD_OBJECT`.
+
+# Protecting Asynchronous Calls across HIDL
+
+Some notes about asynchronous calls across HIDL:
+
+For synchronous calls across HIDL, if an error occurs after the function was called but before it
+returns, HIDL will return a transport error. For example, if the message cannot be delivered to the
+server process or if the server process dies before returning a result, HIDL will return from the
+function with the appropriate transport error in the `Return<>` object, which can be queried with
+`Return<>::isOk()`, `Return<>::isDeadObject()`, `Return<>::description()`, etc.
+
+However, HIDL offers no such error management in the case of asynchronous calls. By default, if the
+client launches an asynchronous task and the server fails to return a result through the callback,
+the client will be left waiting indefinitely for a result it will never receive.
+
+In the NNAPI, `IDevice::prepareModel*` and `IPreparedModel::execute*` (but not
+`IPreparedModel::executeSynchronously*`) are asynchronous calls across HIDL. Specifically, these
+asynchronous functions are called with a HIDL interface callback object (`IPrepareModelCallback` for
+`IDevice::prepareModel*` and `IExecutionCallback` for `IPreparedModel::execute*`) and are expected
+to quickly return, and the results are returned at a later time through these callback objects.
+
+To protect against the case when the server dies after the asynchronous task was called successfully
+but before the results could be returned, HIDL provides an object called a "`hidl_death_recipient`,"
+which can be used to detect when an interface object (and more generally, the server process) has
+died. nnapi/hal/ProtectCallback.h's `DeathHandler` uses `hidl_death_recipient`s to detect when the
+driver process has died, and `DeathHandler` will unblock any thread waiting on the results of an
+`IProtectedCallback` callback object that may otherwise not be signaled. In order for this to work,
+the `IProtectedCallback` object must have been registered via `DeathHandler::protectCallback()`.
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
index 4b32b4e..985cddb 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/InvalidPreparedModel.h
@@ -32,13 +32,13 @@
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
             const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
     std::any getUnderlyingResource() const override;
 };
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h b/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
index 85bd613..c921885 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ProtectCallback.h
@@ -28,6 +28,9 @@
 #include <mutex>
 #include <vector>
 
+// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
+// lifetimes across processes and for protecting asynchronous calls across HIDL.
+
 namespace android::hardware::neuralnetworks::utils {
 
 class IProtectedCallback {
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
index c2940d1..d86c88b 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/ResilientPreparedModel.h
@@ -49,13 +49,13 @@
     nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> execute(
             const nn::Request& request, nn::MeasureTiming measure,
             const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration) const override;
+            const nn::OptionalDuration& loopTimeoutDuration) const override;
 
     nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>> executeFenced(
             const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
             nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-            const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-            const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const override;
+            const nn::OptionalDuration& loopTimeoutDuration,
+            const nn::OptionalDuration& timeoutDurationAfterFence) const override;
 
     std::any getUnderlyingResource() const override;
 
diff --git a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
index 9ae7a63..a46f4ac 100644
--- a/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/InvalidPreparedModel.cpp
@@ -29,7 +29,7 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
 InvalidPreparedModel::execute(const nn::Request& /*request*/, nn::MeasureTiming /*measure*/,
                               const nn::OptionalTimePoint& /*deadline*/,
-                              const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/) const {
+                              const nn::OptionalDuration& /*loopTimeoutDuration*/) const {
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
@@ -37,8 +37,8 @@
 InvalidPreparedModel::executeFenced(
         const nn::Request& /*request*/, const std::vector<nn::SyncFence>& /*waitFor*/,
         nn::MeasureTiming /*measure*/, const nn::OptionalTimePoint& /*deadline*/,
-        const nn::OptionalTimeoutDuration& /*loopTimeoutDuration*/,
-        const nn::OptionalTimeoutDuration& /*timeoutDurationAfterFence*/) const {
+        const nn::OptionalDuration& /*loopTimeoutDuration*/,
+        const nn::OptionalDuration& /*timeoutDurationAfterFence*/) const {
     return NN_ERROR() << "InvalidPreparedModel";
 }
 
diff --git a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
index 1c9ecba..012a1de 100644
--- a/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
+++ b/neuralnetworks/utils/common/src/ResilientPreparedModel.cpp
@@ -64,16 +64,17 @@
 nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>>
 ResilientPreparedModel::execute(const nn::Request& request, nn::MeasureTiming measure,
                                 const nn::OptionalTimePoint& deadline,
-                                const nn::OptionalTimeoutDuration& loopTimeoutDuration) const {
+                                const nn::OptionalDuration& loopTimeoutDuration) const {
     return getPreparedModel()->execute(request, measure, deadline, loopTimeoutDuration);
 }
 
 nn::GeneralResult<std::pair<nn::SyncFence, nn::ExecuteFencedInfoCallback>>
-ResilientPreparedModel::executeFenced(
-        const nn::Request& request, const std::vector<nn::SyncFence>& waitFor,
-        nn::MeasureTiming measure, const nn::OptionalTimePoint& deadline,
-        const nn::OptionalTimeoutDuration& loopTimeoutDuration,
-        const nn::OptionalTimeoutDuration& timeoutDurationAfterFence) const {
+ResilientPreparedModel::executeFenced(const nn::Request& request,
+                                      const std::vector<nn::SyncFence>& waitFor,
+                                      nn::MeasureTiming measure,
+                                      const nn::OptionalTimePoint& deadline,
+                                      const nn::OptionalDuration& loopTimeoutDuration,
+                                      const nn::OptionalDuration& timeoutDurationAfterFence) const {
     return getPreparedModel()->executeFenced(request, waitFor, measure, deadline,
                                              loopTimeoutDuration, timeoutDurationAfterFence);
 }
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 1b0353b..95478a4 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -116,8 +116,8 @@
     ifnames.push_back(buffer.data());
     if (is_bridged) {
         buffer.fill(0);
-        if (property_get("ro.vendor.wifi.sap.concurrent.interface",
-                         buffer.data(), nullptr) == 0) {
+        if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(),
+                         nullptr) == 0) {
             return ifnames;
         }
         ifnames.push_back(buffer.data());
@@ -1841,8 +1841,8 @@
     } else {
         int num_ifaces_need_to_allocate = 2 - instances.size();
         for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
-            std::string instance_name =
-                allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+            std::string instance_name = allocateApOrStaIfaceName(
+                IfaceType::AP, startIdxOfApIface() + i);
             if (!instance_name.empty()) {
                 instances.push_back(instance_name);
             }