• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #ifndef LOG_TAG
8 #define LOG_TAG "ArmnnDriverTests"
9 #endif // LOG_TAG
10 
11 #include "../ArmnnDriver.hpp"
12 #include <iosfwd>
13 #include <android/hidl/allocator/1.0/IAllocator.h>
14 
15 // Some of the short name macros from 'third-party/doctest/doctest.h' clash with macros in
16 // 'system/core/base/include/android-base/logging.h' so we use the full DOCTEST macro names
17 #ifndef DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
18 #define DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
19 #endif // DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES
20 
21 #include <doctest/doctest.h>
22 
23 using RequestArgument = V1_0::RequestArgument;
24 using ::android::hidl::allocator::V1_0::IAllocator;
25 
26 using ::android::hidl::memory::V1_0::IMemory;
27 
28 namespace android
29 {
30 namespace hardware
31 {
32 namespace neuralnetworks
33 {
34 namespace V1_0
35 {
36 
37 std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
38 
39 } // namespace android::hardware::neuralnetworks::V1_0
40 
41 #ifdef ARMNN_ANDROID_NN_V1_3
42 namespace V1_3
43 {
44 
45 std::ostream& operator<<(std::ostream& os, V1_3::ErrorStatus stat);
46 
47 } // namespace android::hardware::neuralnetworks::V1_3
48 #endif
49 
50 } // namespace android::hardware::neuralnetworks
51 } // namespace android::hardware
52 } // namespace android
53 
54 namespace driverTestHelpers
55 {
56 
57 std::ostream& operator<<(std::ostream& os, V1_0::ErrorStatus stat);
58 
59 #ifdef ARMNN_ANDROID_NN_V1_3
60 std::ostream& operator<<(std::ostream& os, V1_3::ErrorStatus stat);
61 #endif
62 
63 struct ExecutionCallback : public V1_0::IExecutionCallback
64 {
ExecutionCallbackdriverTestHelpers::ExecutionCallback65     ExecutionCallback() : mNotified(false) {}
66     Return<void> notify(V1_0::ErrorStatus status) override;
67     /// wait until the callback has notified us that it is done
68     Return<void> wait();
69 
70 private:
71     // use a mutex and a condition variable to wait for asynchronous callbacks
72     std::mutex mMutex;
73     std::condition_variable mCondition;
74     // and a flag, in case we are notified before the wait call
75     bool mNotified;
76 };
77 
78 class PreparedModelCallback : public V1_0::IPreparedModelCallback
79 {
80 public:
PreparedModelCallback()81     PreparedModelCallback()
82         : m_ErrorStatus(V1_0::ErrorStatus::NONE)
83         , m_PreparedModel()
84     { }
~PreparedModelCallback()85     ~PreparedModelCallback() override { }
86 
87     Return<void> notify(V1_0::ErrorStatus status,
88                         const android::sp<V1_0::IPreparedModel>& preparedModel) override;
GetErrorStatus()89     V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
GetPreparedModel()90     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
91 
92 private:
93     V1_0::ErrorStatus                  m_ErrorStatus;
94     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
95 };
96 
97 #if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
98 
99 class PreparedModelCallback_1_2 : public V1_2::IPreparedModelCallback
100 {
101 public:
PreparedModelCallback_1_2()102     PreparedModelCallback_1_2()
103             : m_ErrorStatus(V1_0::ErrorStatus::NONE)
104             , m_PreparedModel()
105             , m_PreparedModel_1_2()
106     { }
~PreparedModelCallback_1_2()107     ~PreparedModelCallback_1_2() override { }
108 
109     Return<void> notify(V1_0::ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override;
110 
111     Return<void> notify_1_2(V1_0::ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override;
112 
GetErrorStatus()113     V1_0::ErrorStatus GetErrorStatus() { return m_ErrorStatus; }
114 
GetPreparedModel()115     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
116 
GetPreparedModel_1_2()117     android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; }
118 
119 private:
120     V1_0::ErrorStatus                   m_ErrorStatus;
121     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
122     android::sp<V1_2::IPreparedModel>  m_PreparedModel_1_2;
123 };
124 
125 #endif
126 
127 #ifdef ARMNN_ANDROID_NN_V1_3
128 
129 class PreparedModelCallback_1_3 : public V1_3::IPreparedModelCallback
130 {
131 public:
PreparedModelCallback_1_3()132     PreparedModelCallback_1_3()
133             : m_1_0_ErrorStatus(V1_0::ErrorStatus::NONE)
134             , m_1_3_ErrorStatus(V1_3::ErrorStatus::NONE)
135             , m_PreparedModel()
136             , m_PreparedModel_1_2()
137             , m_PreparedModel_1_3()
138     { }
~PreparedModelCallback_1_3()139     ~PreparedModelCallback_1_3() override { }
140 
141     Return<void> notify(V1_0::ErrorStatus status, const android::sp<V1_0::IPreparedModel>& preparedModel) override;
142 
143     Return<void> notify_1_2(V1_0::ErrorStatus status, const android::sp<V1_2::IPreparedModel>& preparedModel) override;
144 
145     Return<void> notify_1_3(V1_3::ErrorStatus status, const android::sp<V1_3::IPreparedModel>& preparedModel) override;
146 
GetErrorStatus()147     V1_0::ErrorStatus GetErrorStatus() { return m_1_0_ErrorStatus; }
148 
Get_1_3_ErrorStatus()149     V1_3::ErrorStatus Get_1_3_ErrorStatus() { return m_1_3_ErrorStatus; }
150 
GetPreparedModel()151     android::sp<V1_0::IPreparedModel> GetPreparedModel() { return m_PreparedModel; }
152 
GetPreparedModel_1_2()153     android::sp<V1_2::IPreparedModel> GetPreparedModel_1_2() { return m_PreparedModel_1_2; }
154 
GetPreparedModel_1_3()155     android::sp<V1_3::IPreparedModel> GetPreparedModel_1_3() { return m_PreparedModel_1_3; }
156 
157 private:
158     V1_0::ErrorStatus                   m_1_0_ErrorStatus;
159     V1_3::ErrorStatus                   m_1_3_ErrorStatus;
160     android::sp<V1_0::IPreparedModel>  m_PreparedModel;
161     android::sp<V1_2::IPreparedModel>  m_PreparedModel_1_2;
162     android::sp<V1_3::IPreparedModel>  m_PreparedModel_1_3;
163 };
164 
165 #endif
166 
167 hidl_memory allocateSharedMemory(int64_t size);
168 
169 template<typename T>
AddPoolAndGetData(uint32_t size,V1_0::Request & request)170 android::sp<IMemory> AddPoolAndGetData(uint32_t size, V1_0::Request& request)
171 {
172     hidl_memory pool;
173 
174     android::sp<IAllocator> allocator = IAllocator::getService("ashmem");
175     allocator->allocate(sizeof(T) * size, [&](bool success, const hidl_memory& mem) {
176         DOCTEST_CHECK(success);
177         pool = mem;
178     });
179 
180     request.pools.resize(request.pools.size() + 1);
181     request.pools[request.pools.size() - 1] = pool;
182 
183     android::sp<IMemory> mapped = mapMemory(pool);
184     mapped->update();
185     return mapped;
186 }
187 
188 template<typename T>
AddPoolAndSetData(uint32_t size,V1_0::Request & request,const T * data)189 android::sp<IMemory> AddPoolAndSetData(uint32_t size, V1_0::Request& request, const T* data)
190 {
191     android::sp<IMemory> memory = AddPoolAndGetData<T>(size, request);
192 
193     T* dst = static_cast<T*>(static_cast<void*>(memory->getPointer()));
194 
195     memcpy(dst, data, size * sizeof(T));
196 
197     return memory;
198 }
199 
200 template<typename HalPolicy,
201          typename HalModel   = typename HalPolicy::Model,
202          typename HalOperand = typename HalPolicy::Operand>
AddOperand(HalModel & model,const HalOperand & op)203 void AddOperand(HalModel& model, const HalOperand& op)
204 {
205     model.operands.resize(model.operands.size() + 1);
206     model.operands[model.operands.size() - 1] = op;
207 }
208 
209 template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddBoolOperand(HalModel & model,bool value,uint32_t numberOfConsumers=1)210 void AddBoolOperand(HalModel& model, bool value, uint32_t numberOfConsumers = 1)
211 {
212     using HalOperand         = typename HalPolicy::Operand;
213     using HalOperandType     = typename HalPolicy::OperandType;
214     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
215 
216     V1_0::DataLocation location = {};
217     location.offset = model.operandValues.size();
218     location.length = sizeof(uint8_t);
219 
220     HalOperand op           = {};
221     op.type                 = HalOperandType::BOOL;
222     op.dimensions           = hidl_vec<uint32_t>{};
223     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
224     op.location             = location;
225     op.numberOfConsumers    = numberOfConsumers;
226 
227     model.operandValues.resize(model.operandValues.size() + location.length);
228     *reinterpret_cast<uint8_t*>(&model.operandValues[location.offset]) = static_cast<uint8_t>(value);
229 
230     AddOperand<HalModel>(model, op);
231 }
232 
233 template<typename T>
234 OperandType TypeToOperandType();
235 
236 template<>
237 OperandType TypeToOperandType<float>();
238 
239 template<>
240 OperandType TypeToOperandType<int32_t>();
241 
242 template<typename HalPolicy,
243     typename HalModel       = typename HalPolicy::Model,
244     typename HalOperandType = typename HalPolicy::OperandType>
AddInputOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)245 void AddInputOperand(HalModel& model,
246                      const hidl_vec<uint32_t>& dimensions,
247                      HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
248                      double scale = 0.f,
249                      int offset = 0,
250                      uint32_t numberOfConsumers = 1)
251 {
252     using HalOperand         = typename HalPolicy::Operand;
253     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
254 
255     HalOperand op           = {};
256     op.type                 = operandType;
257     op.scale                = scale;
258     op.zeroPoint            = offset;
259     op.dimensions           = dimensions;
260     op.lifetime             = HalOperandLifeTime::MODEL_INPUT;
261     op.numberOfConsumers    = numberOfConsumers;
262 
263     AddOperand<HalPolicy>(model, op);
264 
265     model.inputIndexes.resize(model.inputIndexes.size() + 1);
266     model.inputIndexes[model.inputIndexes.size() - 1] = model.operands.size() - 1;
267 }
268 
269 template<typename HalPolicy,
270     typename HalModel       = typename HalPolicy::Model,
271     typename HalOperandType = typename HalPolicy::OperandType>
AddOutputOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=0)272 void AddOutputOperand(HalModel& model,
273                       const hidl_vec<uint32_t>& dimensions,
274                       HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
275                       double scale = 0.f,
276                       int offset = 0,
277                       uint32_t numberOfConsumers = 0)
278 {
279     using HalOperand         = typename HalPolicy::Operand;
280     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
281 
282     HalOperand op           = {};
283     op.type                 = operandType;
284     op.scale                = scale;
285     op.zeroPoint            = offset;
286     op.dimensions           = dimensions;
287     op.lifetime             = HalOperandLifeTime::MODEL_OUTPUT;
288     op.numberOfConsumers    = numberOfConsumers;
289 
290     AddOperand<HalPolicy>(model, op);
291 
292     model.outputIndexes.resize(model.outputIndexes.size() + 1);
293     model.outputIndexes[model.outputIndexes.size() - 1] = model.operands.size() - 1;
294 }
295 
296 android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_0::Model& model,
297                                                          armnn_driver::ArmnnDriver& driver,
298                                                          V1_0::ErrorStatus& prepareStatus,
299                                                          V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
300 
301 #if defined(ARMNN_ANDROID_NN_V1_1) || defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
302 
303 android::sp<V1_0::IPreparedModel> PrepareModelWithStatus(const V1_1::Model& model,
304                                                          armnn_driver::ArmnnDriver& driver,
305                                                          V1_0::ErrorStatus& prepareStatus,
306                                                          V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
307 
308 #endif
309 
310 template<typename HalModel>
PrepareModel(const HalModel & model,armnn_driver::ArmnnDriver & driver)311 android::sp<V1_0::IPreparedModel> PrepareModel(const HalModel& model,
312                                                armnn_driver::ArmnnDriver& driver)
313 {
314     V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
315     return PrepareModelWithStatus(model, driver, prepareStatus);
316 }
317 
318 #if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
319 
320 android::sp<V1_2::IPreparedModel> PrepareModelWithStatus_1_2(const armnn_driver::hal_1_2::HalPolicy::Model& model,
321                                                             armnn_driver::ArmnnDriver& driver,
322                                                             V1_0::ErrorStatus& prepareStatus,
323                                                             V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
324 
325 template<typename HalModel>
PrepareModel_1_2(const HalModel & model,armnn_driver::ArmnnDriver & driver)326 android::sp<V1_2::IPreparedModel> PrepareModel_1_2(const HalModel& model,
327                                                    armnn_driver::ArmnnDriver& driver)
328 {
329     V1_0::ErrorStatus prepareStatus = V1_0::ErrorStatus::NONE;
330     return PrepareModelWithStatus_1_2(model, driver, prepareStatus);
331 }
332 
333 #endif
334 
335 #ifdef ARMNN_ANDROID_NN_V1_3
336 
337 template<typename HalPolicy>
AddOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const armnn_driver::hal_1_3::HalPolicy::Operand & op)338 void AddOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
339                 const armnn_driver::hal_1_3::HalPolicy::Operand& op)
340 {
341     model.main.operands.resize(model.main.operands.size() + 1);
342     model.main.operands[model.main.operands.size() - 1] = op;
343 }
344 
345 template<typename HalPolicy>
AddInputOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const hidl_vec<uint32_t> & dimensions,armnn_driver::hal_1_3::HalPolicy::OperandType operandType=armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)346 void AddInputOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
347                      const hidl_vec<uint32_t>& dimensions,
348                      armnn_driver::hal_1_3::HalPolicy::OperandType operandType =
349                      armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,
350                      double scale = 0.f,
351                      int offset = 0,
352                      uint32_t numberOfConsumers = 1)
353 {
354     using HalOperand         = typename armnn_driver::hal_1_3::HalPolicy::Operand;
355     using HalOperandLifeTime = typename armnn_driver::hal_1_3::HalPolicy::OperandLifeTime;
356 
357     HalOperand op           = {};
358     op.type                 = operandType;
359     op.scale                = scale;
360     op.zeroPoint            = offset;
361     op.dimensions           = dimensions;
362     op.lifetime             = HalOperandLifeTime::SUBGRAPH_INPUT;
363     op.numberOfConsumers    = numberOfConsumers;
364 
365     AddOperand<HalPolicy>(model, op);
366 
367     model.main.inputIndexes.resize(model.main.inputIndexes.size() + 1);
368     model.main.inputIndexes[model.main.inputIndexes.size() - 1] = model.main.operands.size() - 1;
369 }
370 
371 template<typename HalPolicy>
AddOutputOperand(armnn_driver::hal_1_3::HalPolicy::Model & model,const hidl_vec<uint32_t> & dimensions,armnn_driver::hal_1_3::HalPolicy::OperandType operandType=armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,double scale=0.f,int offset=0,uint32_t numberOfConsumers=0)372 void AddOutputOperand(armnn_driver::hal_1_3::HalPolicy::Model& model,
373                       const hidl_vec<uint32_t>& dimensions,
374                       armnn_driver::hal_1_3::HalPolicy::OperandType operandType =
375                       armnn_driver::hal_1_3::HalPolicy::OperandType::TENSOR_FLOAT32,
376                       double scale = 0.f,
377                       int offset = 0,
378                       uint32_t numberOfConsumers = 0)
379 {
380     using HalOperand         = typename armnn_driver::hal_1_3::HalPolicy::Operand;
381     using HalOperandLifeTime = typename armnn_driver::hal_1_3::HalPolicy::OperandLifeTime;
382 
383     HalOperand op           = {};
384     op.type                 = operandType;
385     op.scale                = scale;
386     op.zeroPoint            = offset;
387     op.dimensions           = dimensions;
388     op.lifetime             = HalOperandLifeTime::SUBGRAPH_OUTPUT;
389     op.numberOfConsumers    = numberOfConsumers;
390 
391     AddOperand<HalPolicy>(model, op);
392 
393     model.main.outputIndexes.resize(model.main.outputIndexes.size() + 1);
394     model.main.outputIndexes[model.main.outputIndexes.size() - 1] = model.main.operands.size() - 1;
395 }
396 
397 android::sp<V1_3::IPreparedModel> PrepareModelWithStatus_1_3(const armnn_driver::hal_1_3::HalPolicy::Model& model,
398                                                             armnn_driver::ArmnnDriver& driver,
399                                                             V1_3::ErrorStatus& prepareStatus,
400                                                             V1_3::Priority priority = V1_3::Priority::LOW);
401 
402 template<typename HalModel>
PrepareModel_1_3(const HalModel & model,armnn_driver::ArmnnDriver & driver)403 android::sp<V1_3::IPreparedModel> PrepareModel_1_3(const HalModel& model,
404                                                    armnn_driver::ArmnnDriver& driver)
405 {
406     V1_3::ErrorStatus prepareStatus = V1_3::ErrorStatus::NONE;
407     return PrepareModelWithStatus_1_3(model, driver, prepareStatus);
408 }
409 
410 #endif
411 
412 template<typename HalPolicy,
413     typename T,
414     typename HalModel           = typename HalPolicy::Model,
415     typename HalOperandType     = typename HalPolicy::OperandType,
416     typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
AddTensorOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,const T * values,HalOperandType operandType=HalOperandType::TENSOR_FLOAT32,HalOperandLifeTime operandLifeTime=V1_0::OperandLifeTime::CONSTANT_COPY,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)417 void AddTensorOperand(HalModel& model,
418                       const hidl_vec<uint32_t>& dimensions,
419                       const T* values,
420                       HalOperandType operandType = HalOperandType::TENSOR_FLOAT32,
421                       HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
422                       double scale = 0.f,
423                       int offset = 0,
424                       uint32_t numberOfConsumers = 1)
425 {
426     using HalOperand = typename HalPolicy::Operand;
427 
428     uint32_t totalElements = 1;
429     for (uint32_t dim : dimensions)
430     {
431         totalElements *= dim;
432     }
433 
434     V1_0::DataLocation location = {};
435     location.length = totalElements * sizeof(T);
436 
437     if(operandLifeTime == HalOperandLifeTime::CONSTANT_COPY)
438     {
439         location.offset = model.operandValues.size();
440     }
441 
442     HalOperand op           = {};
443     op.type                 = operandType;
444     op.dimensions           = dimensions;
445     op.scale                = scale;
446     op.zeroPoint            = offset;
447     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
448     op.location             = location;
449     op.numberOfConsumers    = numberOfConsumers;
450 
451     model.operandValues.resize(model.operandValues.size() + location.length);
452     for (uint32_t i = 0; i < totalElements; i++)
453     {
454         *(reinterpret_cast<T*>(&model.operandValues[location.offset]) + i) = values[i];
455     }
456 
457     AddOperand<HalPolicy>(model, op);
458 }
459 
460 template<typename HalPolicy,
461     typename T,
462     typename HalModel           = typename HalPolicy::Model,
463     typename HalOperandType     = typename HalPolicy::OperandType,
464     typename HalOperandLifeTime = typename HalPolicy::OperandLifeTime>
AddTensorOperand(HalModel & model,const hidl_vec<uint32_t> & dimensions,const std::vector<T> & values,HalOperandType operandType=HalPolicy::OperandType::TENSOR_FLOAT32,HalOperandLifeTime operandLifeTime=V1_0::OperandLifeTime::CONSTANT_COPY,double scale=0.f,int offset=0,uint32_t numberOfConsumers=1)465 void AddTensorOperand(HalModel& model,
466                       const hidl_vec<uint32_t>& dimensions,
467                       const std::vector<T>& values,
468                       HalOperandType operandType = HalPolicy::OperandType::TENSOR_FLOAT32,
469                       HalOperandLifeTime operandLifeTime = V1_0::OperandLifeTime::CONSTANT_COPY,
470                       double scale = 0.f,
471                       int offset = 0,
472                       uint32_t numberOfConsumers = 1)
473 {
474     AddTensorOperand<HalPolicy, T>(model,
475                                    dimensions,
476                                    values.data(),
477                                    operandType,
478                                    operandLifeTime,
479                                    scale,
480                                    offset,
481                                    numberOfConsumers);
482 }
483 
484 template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddIntOperand(HalModel & model,int32_t value,uint32_t numberOfConsumers=1)485 void AddIntOperand(HalModel& model, int32_t value, uint32_t numberOfConsumers = 1)
486 {
487     using HalOperand         = typename HalPolicy::Operand;
488     using HalOperandType     = typename HalPolicy::OperandType;
489     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
490 
491     V1_0::DataLocation location = {};
492     location.offset = model.operandValues.size();
493     location.length = sizeof(int32_t);
494 
495     HalOperand op           = {};
496     op.type                 = HalOperandType::INT32;
497     op.dimensions           = hidl_vec<uint32_t>{};
498     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
499     op.location             = location;
500     op.numberOfConsumers    = numberOfConsumers;
501 
502     model.operandValues.resize(model.operandValues.size() + location.length);
503     *reinterpret_cast<int32_t*>(&model.operandValues[location.offset]) = value;
504 
505     AddOperand<HalPolicy>(model, op);
506 }
507 
508 template<typename HalPolicy, typename HalModel = typename HalPolicy::Model>
AddFloatOperand(HalModel & model,float value,uint32_t numberOfConsumers=1)509 void AddFloatOperand(HalModel& model,
510                      float value,
511                      uint32_t numberOfConsumers = 1)
512 {
513     using HalOperand         = typename HalPolicy::Operand;
514     using HalOperandType     = typename HalPolicy::OperandType;
515     using HalOperandLifeTime = typename HalPolicy::OperandLifeTime;
516 
517     V1_0::DataLocation location = {};
518     location.offset = model.operandValues.size();
519     location.length = sizeof(float);
520 
521     HalOperand op           = {};
522     op.type                 = HalOperandType::FLOAT32;
523     op.dimensions           = hidl_vec<uint32_t>{};
524     op.lifetime             = HalOperandLifeTime::CONSTANT_COPY;
525     op.location             = location;
526     op.numberOfConsumers    = numberOfConsumers;
527 
528     model.operandValues.resize(model.operandValues.size() + location.length);
529     *reinterpret_cast<float*>(&model.operandValues[location.offset]) = value;
530 
531     AddOperand<HalPolicy>(model, op);
532 }
533 
534 V1_0::ErrorStatus Execute(android::sp<V1_0::IPreparedModel> preparedModel,
535                           const V1_0::Request& request,
536                           V1_0::ErrorStatus expectedStatus = V1_0::ErrorStatus::NONE);
537 
538 android::sp<ExecutionCallback> ExecuteNoWait(android::sp<V1_0::IPreparedModel> preparedModel,
539                                              const V1_0::Request& request);
540 
541 } // namespace driverTestHelpers
542