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