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