• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "CompilationBuilder.h"
18 #include "ExecutionBurstServer.h"
19 #include "HalInterfaces.h"
20 #include "Manager.h"
21 #include "NeuralNetworks.h"
22 #include "NeuralNetworksOEM.h"
23 #include "SampleDriver.h"
24 #include "TestNeuralNetworksWrapper.h"
25 #include "Utils.h"
26 #include "ValidateHal.h"
27 
28 #include <gtest/gtest.h>
29 
30 #include <iterator>
31 #include <map>
32 #include <queue>
33 #include <set>
34 
35 namespace {
36 
37 using namespace ::android;
38 
39 using CompilationBuilder = nn::CompilationBuilder;
40 using Device = nn::Device;
41 using DeviceManager = nn::DeviceManager;
42 using ExecutePreference = nn::test_wrapper::ExecutePreference;
43 using ExecutionBurstServer = nn::ExecutionBurstServer;
44 using HidlModel = hardware::neuralnetworks::V1_2::Model;
45 using HidlToken = hardware::hidl_array<uint8_t, ANEURALNETWORKS_BYTE_SIZE_OF_CACHE_TOKEN>;
46 using PreparedModelCallback = hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
47 using Result = nn::test_wrapper::Result;
48 using SampleDriver = nn::sample_driver::SampleDriver;
49 using SamplePreparedModel = nn::sample_driver::SamplePreparedModel;
50 using WrapperModel = nn::test_wrapper::Model;
51 using WrapperOperandType = nn::test_wrapper::OperandType;
52 using WrapperType = nn::test_wrapper::Type;
53 
54 template <typename T>
55 using MQDescriptorSync = hardware::MQDescriptorSync<T>;
56 
57 const Timing kBadTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
58 
59 // This is an IDevice for testing purposes. The test driver has customized
60 // getCapabilities_1_1 and getSupportedOperations_1_2.
61 class TestDriver : public SampleDriver {
62    public:
TestDriver(const char * name,Capabilities capabilities,const std::vector<bool> & supportedOps)63     TestDriver(const char* name, Capabilities capabilities, const std::vector<bool>& supportedOps)
64         : SampleDriver(name), mCapabilities(capabilities), mSupportedOps(supportedOps) {}
~TestDriver()65     ~TestDriver() override {}
66 
getCapabilities_1_2(getCapabilities_1_2_cb cb)67     Return<void> getCapabilities_1_2(getCapabilities_1_2_cb cb) override {
68         cb(ErrorStatus::NONE, mCapabilities);
69         return Void();
70     }
71 
getSupportedOperations_1_2(const Model & model,getSupportedOperations_cb cb)72     Return<void> getSupportedOperations_1_2(const Model& model,
73                                             getSupportedOperations_cb cb) override {
74         if (!android::nn::validateModel(model)) {
75             cb(ErrorStatus::INVALID_ARGUMENT, std::vector<bool>());
76             return Void();
77         }
78         const size_t count = model.operations.size();
79         std::vector<bool> supported(count);
80         std::transform(
81                 model.operations.begin(), model.operations.end(), supported.begin(),
82                 [this](Operation op) { return mSupportedOps[static_cast<int32_t>(op.type)]; });
83         cb(ErrorStatus::NONE, supported);
84         return Void();
85     }
86 
87    private:
88     Capabilities mCapabilities;
89     std::vector<bool> mSupportedOps;
90 };
91 
92 class IntrospectionControlTest : public ::testing::Test {
93    protected:
SetUp()94     virtual void SetUp() {}
TearDown()95     virtual void TearDown() {
96         if (mEvent) {
97             ANeuralNetworksEvent_free(mEvent);
98         }
99         if (mExecution) {
100             ANeuralNetworksExecution_free(mExecution);
101         }
102         if (mCompilation) {
103             ANeuralNetworksCompilation_free(mCompilation);
104         }
105         DeviceManager::get()->forTest_reInitializeDeviceList();
106     }
107 
108     struct DeviceSpecification {
DeviceSpecification__anon062581700111::IntrospectionControlTest::DeviceSpecification109         DeviceSpecification(const std::string& name, float perf, std::vector<bool>& supportedOps)
110             : mName(name), mSupportedOps(supportedOps) {
111             PerformanceInfo perfInfo = {.execTime = perf, .powerUsage = perf};
112             mCapabilities = {.relaxedFloat32toFloat16PerformanceScalar = perfInfo,
113                              .relaxedFloat32toFloat16PerformanceTensor = perfInfo,
114                              .operandPerformance = nn::nonExtensionOperandPerformance(perfInfo)};
115         }
116         std::string mName;
117         Capabilities mCapabilities;
118         std::vector<bool> mSupportedOps;
119     };
120 
121     // From a vector of DeviceSpecification, register new Devices.
registerDevices(std::vector<DeviceSpecification> specifications)122     void registerDevices(std::vector<DeviceSpecification> specifications) {
123         for (const auto& specification : specifications) {
124             DeviceManager::get()->forTest_registerDevice(
125                     specification.mName.c_str(),
126                     new TestDriver(specification.mName.c_str(), specification.mCapabilities,
127                                    specification.mSupportedOps));
128         }
129     }
130 
selectDeviceByName(const std::string & name)131     bool selectDeviceByName(const std::string& name) {
132         uint32_t numDevices = 0;
133         EXPECT_EQ(ANeuralNetworks_getDeviceCount(&numDevices), ANEURALNETWORKS_NO_ERROR);
134         EXPECT_GE(numDevices, (uint32_t)1);
135 
136         for (uint32_t i = 0; i < numDevices; i++) {
137             ANeuralNetworksDevice* device = nullptr;
138             EXPECT_EQ(ANeuralNetworks_getDevice(i, &device), ANEURALNETWORKS_NO_ERROR);
139             const char* buffer = nullptr;
140             int result = ANeuralNetworksDevice_getName(device, &buffer);
141             if (result == ANEURALNETWORKS_NO_ERROR && name.compare(buffer) == 0) {
142                 mDevices.push_back(device);
143                 return true;
144             }
145         }
146         return false;
147     }
148 
isSupportedOpListExpected(const std::vector<bool> & expected)149     bool isSupportedOpListExpected(const std::vector<bool>& expected) {
150         const uint32_t kMaxNumberOperations = 256;
151         EXPECT_LE(expected.size(), kMaxNumberOperations);
152         ANeuralNetworksModel* modelHandle = mModel.getHandle();
153         bool supported[kMaxNumberOperations] = {false};
154         EXPECT_EQ(ANeuralNetworksModel_getSupportedOperationsForDevices(
155                           modelHandle, mDevices.data(), mDevices.size(), supported),
156                   ANEURALNETWORKS_NO_ERROR);
157         return std::equal(expected.begin(), expected.end(), supported);
158     }
159 
prepareForExecution(bool measureTiming=false)160     int prepareForExecution(bool measureTiming = false) {
161         ANeuralNetworksModel* modelHandle = mModel.getHandle();
162         int result = ANeuralNetworksCompilation_createForDevices(modelHandle, mDevices.data(),
163                                                                  mDevices.size(), &mCompilation);
164         if (result != ANEURALNETWORKS_NO_ERROR) {
165             return result;
166         }
167         EXPECT_EQ(ANeuralNetworksCompilation_finish(mCompilation), ANEURALNETWORKS_NO_ERROR);
168         EXPECT_EQ(ANeuralNetworksExecution_create(mCompilation, &mExecution),
169                   ANEURALNETWORKS_NO_ERROR);
170         if (measureTiming) {
171             // Don't call setMeasureTiming unless we need to -- cannot call this
172             // API unless there is exactly one device.
173             EXPECT_EQ(ANeuralNetworksExecution_setMeasureTiming(mExecution, true),
174                       ANEURALNETWORKS_NO_ERROR);
175         }
176         return ANEURALNETWORKS_NO_ERROR;
177     }
178 
179     std::vector<ANeuralNetworksDevice*> mDevices;
180     ANeuralNetworksEvent* mEvent = nullptr;
181     ANeuralNetworksExecution* mExecution = nullptr;
182     ANeuralNetworksCompilation* mCompilation = nullptr;
183     WrapperModel mModel;
184 };
185 
createSimpleAddModel(WrapperModel * model)186 void createSimpleAddModel(WrapperModel* model) {
187     WrapperOperandType type0(WrapperType::TENSOR_FLOAT32, {2});
188     WrapperOperandType type1(WrapperType::INT32, {});
189     // Phase 1, operands
190     auto op1 = model->addOperand(&type0);
191     auto op2 = model->addOperand(&type0);
192     auto act = model->addOperand(&type1);
193     auto op3 = model->addOperand(&type0);
194     // Phase 2, operations
195     static int32_t act_init[] = {0};
196     model->setOperandValue(act, act_init, sizeof(act_init));
197     model->addOperation(ANEURALNETWORKS_ADD, {op1, op2, act}, {op3});
198     // Phase 3, inputs and outputs
199     model->identifyInputsAndOutputs({op1, op2}, {op3});
200     model->finish();
201     ASSERT_TRUE(model->isValid());
202 }
203 
204 // This test verifies that a simple ADD model is able to run on a single device that claims being
205 // able to handle all operations.
TEST_F(IntrospectionControlTest,SimpleAddModel)206 TEST_F(IntrospectionControlTest, SimpleAddModel) {
207     // This is needed before we have the CPU fallback path being treated as a Device.
208     // TODO(miaowang): remove once b/72506261 is fixed.
209     if (DeviceManager::get()->getUseCpuOnly()) {
210         GTEST_SKIP();
211     }
212 
213     createSimpleAddModel(&mModel);
214 
215     std::string driverName = "test-all";
216     std::vector<bool> ops(android::nn::kNumberOfOperationTypes, true);
217     registerDevices({{driverName, 0.9, ops}});
218 
219     EXPECT_TRUE(selectDeviceByName(driverName));
220     EXPECT_TRUE(isSupportedOpListExpected({true}));
221     EXPECT_EQ(prepareForExecution(), ANEURALNETWORKS_NO_ERROR);
222 
223     // Verify that the mCompilation is actually using the "test-all" device.
224     CompilationBuilder* c = reinterpret_cast<CompilationBuilder*>(mCompilation);
225     const char* deviceNameBuffer =
226             c->forTest_getExecutionPlan().forTest_simpleGetDevice()->getName();
227     EXPECT_TRUE(driverName.compare(deviceNameBuffer) == 0);
228 
229     float input1[2] = {1.0f, 2.0f};
230     float input2[2] = {3.0f, 4.0f};
231     float output[2];
232     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 0, nullptr, input1, sizeof(input1)),
233               ANEURALNETWORKS_NO_ERROR);
234     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 1, nullptr, input2, sizeof(input2)),
235               ANEURALNETWORKS_NO_ERROR);
236     EXPECT_EQ(ANeuralNetworksExecution_setOutput(mExecution, 0, nullptr, output, sizeof(output)),
237               ANEURALNETWORKS_NO_ERROR);
238     EXPECT_EQ(ANeuralNetworksExecution_setMeasureTiming(mExecution, true),
239               ANEURALNETWORKS_NO_ERROR);
240 
241     EXPECT_EQ(ANeuralNetworksExecution_startCompute(mExecution, &mEvent), ANEURALNETWORKS_NO_ERROR);
242     EXPECT_EQ(ANeuralNetworksEvent_wait(mEvent), ANEURALNETWORKS_NO_ERROR);
243     EXPECT_EQ(output[0], input1[0] + input2[0]);
244     EXPECT_EQ(output[1], input1[1] + input2[1]);
245 
246     uint64_t timeOnHardware, timeInDriver;
247     EXPECT_EQ(ANeuralNetworksExecution_getDuration(mExecution, ANEURALNETWORKS_DURATION_ON_HARDWARE,
248                                                    &timeOnHardware),
249               ANEURALNETWORKS_NO_ERROR);
250     EXPECT_EQ(ANeuralNetworksExecution_getDuration(mExecution, ANEURALNETWORKS_DURATION_IN_DRIVER,
251                                                    &timeInDriver),
252               ANEURALNETWORKS_NO_ERROR);
253     if (timeOnHardware != UINT64_MAX && timeInDriver != UINT64_MAX) {
254         EXPECT_LE(timeOnHardware, timeInDriver);
255     }
256 }
257 
258 /*-- Begin timing tests -------------------------------------------------------------------------*/
259 
260 namespace timing_tests {
261 
262 constexpr Timing kGoodTiming = {.timeOnDevice = 123, .timeInDriver = 456};
263 
264 enum class DriverKind {
265     CPU,
266     OLD,  // too old to support timing (1.1 or earlier)
267     NEW   // new enough to support timing (1.2 or later)
268 };
269 
operator <<(std::ostream & os,DriverKind kind)270 std::ostream& operator<<(std::ostream& os, DriverKind kind) {
271     const char* names[] = {"CPU", "OLD", "NEW"};
272     const uint32_t index = static_cast<uint32_t>(kind);
273     CHECK(index < std::size(names));
274     return os << names[index];
275 }
276 
277 enum class Success {
278     // ASYNC: Return ErrorStatus::NONE; notify ErrorStatus::NONE and timing
279     // SYNC, BURST: Return ErrorStatus::NONE and timing
280     PASS_NEITHER,  // timing = kBadTiming
281     PASS_DEVICE,   // timing = kGoodTiming.timeOnDevice, kBadTiming.timeInDriver
282     PASS_DRIVER,   // timing = kBadTiming.timeOnDevice, kGoodTiming.timeInDriver
283     PASS_BOTH,     // timing = kGoodTiming
284     PASS_CPU,      // timing = { kBadTiming.timeOnDevice or 0, kBadTiming.timeInDriver or 0 }
285 
286     // ASYNC: Return ErrorStatus::GENERAL_FAILURE; notify ErrorStatus::GENERAL_FAILURE and
287     // kBadTiming
288     // SYNC, BURST: Return ErrorStatus::GENERAL_FAILURE and kBadTiming
289     FAIL_LAUNCH,
290 
291     // ASYNC: Return ErrorStatus::NONE; notify ErrorStatus::GENERAL_FAILURE and kBadTiming
292     FAIL_WAIT
293 };
294 
operator <<(std::ostream & os,Success success)295 std::ostream& operator<<(std::ostream& os, Success success) {
296     const char* names[] = {"PASS_NEITHER", "PASS_DEVICE", "PASS_DRIVER", "PASS_BOTH",
297                            "PASS_CPU",     "FAIL_LAUNCH", "FAIL_WAIT"};
298     const uint32_t index = static_cast<uint32_t>(success);
299     CHECK(index < std::size(names));
300     return os << names[index];
301 }
302 
303 std::map<Success, Timing> expectedTimingMap = {
304         {Success::PASS_NEITHER, kBadTiming},
305         {Success::PASS_DEVICE,
306          {.timeOnDevice = kGoodTiming.timeOnDevice, .timeInDriver = kBadTiming.timeInDriver}},
307         {Success::PASS_DRIVER,
308          {.timeOnDevice = kBadTiming.timeOnDevice, .timeInDriver = kGoodTiming.timeInDriver}},
309         {Success::PASS_BOTH, kGoodTiming},
310         {Success::FAIL_LAUNCH, kBadTiming},
311         {Success::FAIL_WAIT, kBadTiming}};
312 
313 std::set<Success> expectedPassSet = {Success::PASS_NEITHER, Success::PASS_DEVICE,
314                                      Success::PASS_DRIVER, Success::PASS_BOTH, Success::PASS_CPU};
315 
316 enum class Compute { ASYNC, SYNC, BURST };
317 
operator <<(std::ostream & os,Compute compute)318 std::ostream& operator<<(std::ostream& os, Compute compute) {
319     const char* names[] = {"ASYNC", "SYNC", "BURST"};
320     const uint32_t index = static_cast<uint32_t>(compute);
321     CHECK(index < std::size(names));
322     return os << names[index];
323 }
324 
325 // For these tests we don't care about actually running an inference -- we
326 // just want to dummy up execution status and timing results.
327 class TestPreparedModel12 : public SamplePreparedModel {
328    public:
TestPreparedModel12(const HidlModel & model,const SampleDriver * driver,Success success)329     TestPreparedModel12(const HidlModel& model, const SampleDriver* driver, Success success)
330         : SamplePreparedModel(model, driver), mSuccess(success) {}
331 
execute(const Request &,const sp<V1_0::IExecutionCallback> & callback)332     Return<ErrorStatus> execute(const Request&,
333                                 const sp<V1_0::IExecutionCallback>& callback) override {
334         switch (mSuccess) {
335             case Success::PASS_NEITHER:
336                 callback->notify(ErrorStatus::NONE);
337                 return ErrorStatus::NONE;
338             case Success::FAIL_LAUNCH:
339                 callback->notify(ErrorStatus::GENERAL_FAILURE);
340                 return ErrorStatus::GENERAL_FAILURE;
341             case Success::FAIL_WAIT:
342                 callback->notify(ErrorStatus::GENERAL_FAILURE);
343                 return ErrorStatus::NONE;
344             default:
345                 ADD_FAILURE() << "Unexpected Success kind";
346                 return ErrorStatus::GENERAL_FAILURE;
347         }
348     }
349 
execute_1_2(const Request &,MeasureTiming measure,const sp<V1_2::IExecutionCallback> & callback)350     Return<ErrorStatus> execute_1_2(const Request&, MeasureTiming measure,
351                                     const sp<V1_2::IExecutionCallback>& callback) override {
352         EXPECT_EQ(measure, MeasureTiming::YES);
353         switch (mSuccess) {
354             case Success::PASS_NEITHER:
355             case Success::PASS_DEVICE:
356             case Success::PASS_DRIVER:
357             case Success::PASS_BOTH:
358                 callback->notify_1_2(ErrorStatus::NONE, {}, expectedTimingMap.at(mSuccess));
359                 return ErrorStatus::NONE;
360             case Success::FAIL_LAUNCH:
361                 callback->notify(ErrorStatus::GENERAL_FAILURE);
362                 return ErrorStatus::GENERAL_FAILURE;
363             case Success::FAIL_WAIT:
364                 callback->notify(ErrorStatus::GENERAL_FAILURE);
365                 return ErrorStatus::NONE;
366             default:
367                 ADD_FAILURE() << "Unexpected Success kind";
368                 return ErrorStatus::GENERAL_FAILURE;
369         }
370     }
371 
executeSynchronously(const Request &,MeasureTiming measure,executeSynchronously_cb cb)372     Return<void> executeSynchronously(const Request&, MeasureTiming measure,
373                                       executeSynchronously_cb cb) override {
374         EXPECT_EQ(measure, MeasureTiming::YES);
375         switch (mSuccess) {
376             case Success::PASS_NEITHER:
377             case Success::PASS_DEVICE:
378             case Success::PASS_DRIVER:
379             case Success::PASS_BOTH:
380                 cb(ErrorStatus::NONE, {}, expectedTimingMap.at(mSuccess));
381                 return Void();
382             case Success::FAIL_LAUNCH:
383             case Success::FAIL_WAIT:
384                 // While this is a synchronous execution method, the NNAPI
385                 // runtime may call it even for asynchronous execution, so we
386                 // need to tolerate Success::FAIL_WAIT here, not just
387                 // Success::FAIL_LAUNCH.
388                 cb(ErrorStatus::GENERAL_FAILURE, {}, kBadTiming);
389                 return Void();
390             default:
391                 ADD_FAILURE() << "Unexpected Success kind";
392                 cb(ErrorStatus::GENERAL_FAILURE, {}, kBadTiming);
393                 return Void();
394         }
395     }
396 
397     // ExecutionBurstServer::create has an overload that will use
398     // IPreparedModel::executeSynchronously(), so we can rely on that, rather
399     // than having to implement ExecutionBurstServer::IExecutorWithCache.
configureExecutionBurst(const sp<V1_2::IBurstCallback> & callback,const MQDescriptorSync<V1_2::FmqRequestDatum> & requestChannel,const MQDescriptorSync<V1_2::FmqResultDatum> & resultChannel,configureExecutionBurst_cb cb)400     Return<void> configureExecutionBurst(
401             const sp<V1_2::IBurstCallback>& callback,
402             const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
403             const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
404             configureExecutionBurst_cb cb) override {
405         const sp<V1_2::IBurstContext> burst =
406                 ExecutionBurstServer::create(callback, requestChannel, resultChannel, this);
407 
408         cb(burst == nullptr ? ErrorStatus::GENERAL_FAILURE : ErrorStatus::NONE, burst);
409         return Void();
410     }
411 
412    private:
413     Success mSuccess;
414 };
415 
416 // Like TestPreparedModel12, but implementing 1.0
417 class TestPreparedModel10 : public V1_0::IPreparedModel {
418    public:
TestPreparedModel10(const HidlModel & model,const SampleDriver * driver,Success success)419     TestPreparedModel10(const HidlModel& model, const SampleDriver* driver, Success success)
420         : m12PreparedModel(new TestPreparedModel12(model, driver, success)) {}
421 
execute(const Request & request,const sp<V1_0::IExecutionCallback> & callback)422     Return<ErrorStatus> execute(const Request& request,
423                                 const sp<V1_0::IExecutionCallback>& callback) override {
424         return m12PreparedModel->execute(request, callback);
425     }
426 
427    private:
428     const sp<V1_2::IPreparedModel> m12PreparedModel;
429 };
430 
431 // Behaves like SampleDriver, except that it produces customized IPrepareModel.
432 class TestDriver12 : public SampleDriver {
433    public:
TestDriver12(const std::string & name,Success success)434     TestDriver12(const std::string& name, Success success)
435         : SampleDriver(name.c_str()), mSuccess(success) {}
436 
getCapabilities_1_2(getCapabilities_1_2_cb _hidl_cb)437     Return<void> getCapabilities_1_2(getCapabilities_1_2_cb _hidl_cb) override {
438         android::nn::initVLogMask();
439         const PerformanceInfo kPerf = {.execTime = 0.75f, .powerUsage = 0.75f};
440         Capabilities capabilities = {
441                 .relaxedFloat32toFloat16PerformanceScalar = kPerf,
442                 .relaxedFloat32toFloat16PerformanceTensor = kPerf,
443                 .operandPerformance = nn::nonExtensionOperandPerformance(kPerf)};
444         _hidl_cb(ErrorStatus::NONE, capabilities);
445         return Void();
446     }
447 
getSupportedOperations_1_2(const HidlModel & model,getSupportedOperations_1_2_cb cb)448     Return<void> getSupportedOperations_1_2(const HidlModel& model,
449                                             getSupportedOperations_1_2_cb cb) override {
450         if (nn::validateModel(model)) {
451             std::vector<bool> supported(model.operations.size(), true);
452             cb(ErrorStatus::NONE, supported);
453         } else {
454             std::vector<bool> supported;
455             cb(ErrorStatus::INVALID_ARGUMENT, supported);
456         }
457         return Void();
458     }
459 
prepareModel_1_2(const HidlModel & model,ExecutionPreference,const hidl_vec<hidl_handle> &,const hidl_vec<hidl_handle> &,const HidlToken &,const sp<IPreparedModelCallback> & callback)460     Return<ErrorStatus> prepareModel_1_2(const HidlModel& model, ExecutionPreference,
461                                          const hidl_vec<hidl_handle>&, const hidl_vec<hidl_handle>&,
462                                          const HidlToken&,
463                                          const sp<IPreparedModelCallback>& callback) override {
464         callback->notify_1_2(ErrorStatus::NONE, new TestPreparedModel12(model, this, mSuccess));
465         return ErrorStatus::NONE;
466     }
467 
prepareModel_1_1(const V1_1::Model & model,ExecutionPreference,const sp<V1_0::IPreparedModelCallback> & callback)468     Return<ErrorStatus> prepareModel_1_1(
469             const V1_1::Model& model, ExecutionPreference,
470             const sp<V1_0::IPreparedModelCallback>& callback) override {
471         callback->notify(ErrorStatus::NONE,
472                          new TestPreparedModel10(nn::convertToV1_2(model), this, mSuccess));
473         return ErrorStatus::NONE;
474     }
475 
prepareModel(const V1_0::Model & model,const sp<V1_0::IPreparedModelCallback> & callback)476     Return<ErrorStatus> prepareModel(const V1_0::Model& model,
477                                      const sp<V1_0::IPreparedModelCallback>& callback) override {
478         return prepareModel_1_1(nn::convertToV1_1(model), ExecutionPreference::FAST_SINGLE_ANSWER,
479                                 callback);
480     }
481 
482    private:
483     Success mSuccess;
484 };
485 
486 // Like TestDriver, but implementing 1.1
487 class TestDriver11 : public V1_1::IDevice {
488    public:
TestDriver11(const std::string & name,Success success)489     TestDriver11(const std::string& name, Success success)
490         : m12Driver(new TestDriver12(name, success)) {}
getCapabilities_1_1(getCapabilities_1_1_cb _hidl_cb)491     Return<void> getCapabilities_1_1(getCapabilities_1_1_cb _hidl_cb) override {
492         return m12Driver->getCapabilities_1_1(_hidl_cb);
493     }
getSupportedOperations_1_1(const V1_1::Model & model,getSupportedOperations_1_1_cb _hidl_cb)494     Return<void> getSupportedOperations_1_1(const V1_1::Model& model,
495                                             getSupportedOperations_1_1_cb _hidl_cb) override {
496         return m12Driver->getSupportedOperations_1_1(model, _hidl_cb);
497     }
prepareModel_1_1(const V1_1::Model & model,ExecutionPreference preference,const sp<V1_0::IPreparedModelCallback> & actualCallback)498     Return<ErrorStatus> prepareModel_1_1(
499             const V1_1::Model& model, ExecutionPreference preference,
500             const sp<V1_0::IPreparedModelCallback>& actualCallback) override {
501         return m12Driver->prepareModel_1_1(model, preference, actualCallback);
502     }
getStatus()503     Return<DeviceStatus> getStatus() override { return m12Driver->getStatus(); }
getCapabilities(getCapabilities_cb _hidl_cb)504     Return<void> getCapabilities(getCapabilities_cb _hidl_cb) override {
505         return m12Driver->getCapabilities(_hidl_cb);
506     }
getSupportedOperations(const V1_0::Model & model,getSupportedOperations_cb _hidl_cb)507     Return<void> getSupportedOperations(const V1_0::Model& model,
508                                         getSupportedOperations_cb _hidl_cb) override {
509         return m12Driver->getSupportedOperations(model, _hidl_cb);
510     }
prepareModel(const V1_0::Model & model,const sp<V1_0::IPreparedModelCallback> & actualCallback)511     Return<ErrorStatus> prepareModel(
512             const V1_0::Model& model,
513             const sp<V1_0::IPreparedModelCallback>& actualCallback) override {
514         return m12Driver->prepareModel(model, actualCallback);
515     }
516 
517    private:
518     const sp<V1_2::IDevice> m12Driver;
519 };
520 
521 class TimingTest : public IntrospectionControlTest,
522                    public ::testing::WithParamInterface<std::tuple<DriverKind, Success, Compute>> {
523    public:
TimingTest()524     TimingTest()
525         : kDriverKind(std::get<0>(GetParam())),
526           kSuccess(std::get<1>(GetParam())),
527           kCompute(std::get<2>(GetParam())) {}
528 
529    protected:
530     const DriverKind kDriverKind;
531     const Success kSuccess;
532     const Compute kCompute;
533 };
534 
TEST_P(TimingTest,Test)535 TEST_P(TimingTest, Test) {
536     // There's no straightforward way to force CPU execution to fail.
537     ASSERT_EQ(kDriverKind == DriverKind::CPU, kSuccess == Success::PASS_CPU);
538 
539     // FAIL_WAIT only makes sense for ASYNC.
540     ASSERT_TRUE(kCompute == Compute::ASYNC || kSuccess != Success::FAIL_WAIT);
541 
542     if (DeviceManager::get()->getUseCpuOnly() != (kDriverKind == DriverKind::CPU)) {
543         // We don't have an elegant way to request the CPU driver.  Therefore,
544         // we rely on our test framework to make the choice between CPU and
545         // non-CPU.
546         GTEST_SKIP();
547     }
548 
549     createSimpleAddModel(&mModel);
550 
551     switch (kDriverKind) {
552         case DriverKind::CPU: {
553             // There should be only one driver -- the CPU
554             const char* name = DeviceManager::get()->getDrivers()[0]->getName();
555             ASSERT_TRUE(selectDeviceByName(name));
556             break;
557         }
558         case DriverKind::OLD: {
559             static const char name[] = "old";
560             DeviceManager::get()->forTest_registerDevice(name, new TestDriver11(name, kSuccess));
561             ASSERT_TRUE(selectDeviceByName(name));
562             break;
563         }
564         case DriverKind::NEW: {
565             static const char name[] = "new";
566             DeviceManager::get()->forTest_registerDevice(name, new TestDriver12(name, kSuccess));
567             ASSERT_TRUE(selectDeviceByName(name));
568             break;
569         }
570         default:
571             FAIL() << "Unexpected DriverKind";
572     }
573 
574     EXPECT_EQ(prepareForExecution(true /*measureTiming*/), ANEURALNETWORKS_NO_ERROR);
575 
576     float input1[2] = {1.0f, 2.0f};
577     float input2[2] = {3.0f, 4.0f};
578     float output[2];
579     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 0, nullptr, input1, sizeof(input1)),
580               ANEURALNETWORKS_NO_ERROR);
581     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 1, nullptr, input2, sizeof(input2)),
582               ANEURALNETWORKS_NO_ERROR);
583     EXPECT_EQ(ANeuralNetworksExecution_setOutput(mExecution, 0, nullptr, output, sizeof(output)),
584               ANEURALNETWORKS_NO_ERROR);
585     EXPECT_EQ(ANeuralNetworksExecution_setMeasureTiming(mExecution, true),
586               ANEURALNETWORKS_NO_ERROR);
587 
588     auto Check = [](bool expectPass, int result) {
589         if (expectPass) {
590             ASSERT_EQ(result, ANEURALNETWORKS_NO_ERROR);
591         } else {
592             ASSERT_NE(result, ANEURALNETWORKS_NO_ERROR);
593         }
594     };
595 
596     const bool isPass = expectedPassSet.count(kSuccess) != 0;
597 
598     switch (kCompute) {
599         case Compute::ASYNC: {
600             // Ideally what we'd like to do here is
601             //
602             //     Check(kSuccess != Success::FAIL_LAUNCH,
603             //         ANeuralNetworksExecution_startCompute(mExecution, &mEvent));
604             //     Check(isPass, ANeuralNetworksEvent_wait(mEvent));
605             //
606             // However, in the current implementation of the runtime, a launch
607             // failure at the HAL level does not show up as a launch failure at
608             // the NDK level ("startCompute"): The NNAPI runtime does not call a
609             // driver until it (the runtime) begins execution, so a launch
610             // failure at the HAL level looks like an execution failure at the
611             // NDK level ("wait").
612             SCOPED_TRACE("ASYNC startCompute");
613             Check(true,  // rather than kSuccess != Success::FAIL_LAUNCH
614                   ANeuralNetworksExecution_startCompute(mExecution, &mEvent));
615             SCOPED_TRACE("ASYNC wait");
616             Check(isPass, ANeuralNetworksEvent_wait(mEvent));
617             break;
618         }
619         case Compute::SYNC: {
620             SCOPED_TRACE("SYNC");
621             Check(isPass, ANeuralNetworksExecution_compute(mExecution));
622             break;
623         }
624         case Compute::BURST: {
625             SCOPED_TRACE("BURST");
626             ANeuralNetworksBurst* burst;
627             ASSERT_EQ(ANeuralNetworksBurst_create(mCompilation, &burst), ANEURALNETWORKS_NO_ERROR);
628             Check(isPass, ANeuralNetworksExecution_burstCompute(mExecution, burst));
629             ANeuralNetworksBurst_free(burst);
630             break;
631         }
632         default:
633             FAIL() << "unreachable";
634     }
635 
636     uint64_t timeOnHardware, timeInDriver;
637     EXPECT_EQ(ANeuralNetworksExecution_getDuration(mExecution, ANEURALNETWORKS_DURATION_ON_HARDWARE,
638                                                    &timeOnHardware),
639               ANEURALNETWORKS_NO_ERROR);
640     EXPECT_EQ(ANeuralNetworksExecution_getDuration(mExecution, ANEURALNETWORKS_DURATION_IN_DRIVER,
641                                                    &timeInDriver),
642               ANEURALNETWORKS_NO_ERROR);
643     switch (kDriverKind) {
644         case DriverKind::CPU: {
645             // TODO: Should we require timing to be reported as 0?
646             EXPECT_TRUE(timeOnHardware == 0 || timeOnHardware == UINT64_MAX)
647                     << "timeOnHardware = " << timeOnHardware;
648             EXPECT_TRUE(timeInDriver == 0 || timeInDriver == UINT64_MAX)
649                     << "timeInDriver = " << timeOnHardware;
650             break;
651         }
652         case DriverKind::OLD: {
653             EXPECT_EQ(timeOnHardware, UINT64_MAX);
654             EXPECT_EQ(timeInDriver, UINT64_MAX);
655             break;
656         }
657         case DriverKind::NEW: {
658             auto microsToNanos = [](uint64_t micros) {
659                 constexpr uint64_t kNanosPerMicro = 1000;
660                 return micros == UINT64_MAX ? UINT64_MAX : kNanosPerMicro * micros;
661             };
662             const Timing expectedTiming = expectedTimingMap.at(kSuccess);
663             EXPECT_EQ(timeOnHardware, microsToNanos(expectedTiming.timeOnDevice));
664             EXPECT_EQ(timeInDriver, microsToNanos(expectedTiming.timeInDriver));
665             break;
666         }
667         default:
668             FAIL() << "unreachable";
669     }
670     if (timeOnHardware != UINT64_MAX && timeInDriver != UINT64_MAX) {
671         EXPECT_LE(timeOnHardware, timeInDriver);
672     }
673 }
674 
675 auto kTimingTestValues = ::testing::Values(
676         // NOTE: We cannot force CPU execution to fail
677         std::make_tuple(DriverKind::CPU, Success::PASS_CPU, Compute::ASYNC),
678         std::make_tuple(DriverKind::CPU, Success::PASS_CPU, Compute::SYNC),
679         std::make_tuple(DriverKind::CPU, Success::PASS_CPU, Compute::BURST),
680 
681         // NOTE: OLD driver does not provide timing
682         std::make_tuple(DriverKind::OLD, Success::PASS_NEITHER, Compute::ASYNC),
683         std::make_tuple(DriverKind::OLD, Success::PASS_NEITHER, Compute::SYNC),
684         std::make_tuple(DriverKind::OLD, Success::PASS_NEITHER, Compute::BURST),
685 
686         std::make_tuple(DriverKind::OLD, Success::FAIL_LAUNCH, Compute::ASYNC),
687         std::make_tuple(DriverKind::OLD, Success::FAIL_LAUNCH, Compute::SYNC),
688         std::make_tuple(DriverKind::OLD, Success::FAIL_LAUNCH, Compute::BURST),
689 
690         // NOTE: Only ASYNC is paired with a wait
691         std::make_tuple(DriverKind::OLD, Success::FAIL_WAIT, Compute::ASYNC),
692 
693         std::make_tuple(DriverKind::NEW, Success::PASS_NEITHER, Compute::ASYNC),
694         std::make_tuple(DriverKind::NEW, Success::PASS_NEITHER, Compute::SYNC),
695         std::make_tuple(DriverKind::NEW, Success::PASS_NEITHER, Compute::BURST),
696 
697         std::make_tuple(DriverKind::NEW, Success::PASS_DEVICE, Compute::ASYNC),
698         std::make_tuple(DriverKind::NEW, Success::PASS_DEVICE, Compute::SYNC),
699         std::make_tuple(DriverKind::NEW, Success::PASS_DEVICE, Compute::BURST),
700 
701         std::make_tuple(DriverKind::NEW, Success::PASS_DRIVER, Compute::ASYNC),
702         std::make_tuple(DriverKind::NEW, Success::PASS_DRIVER, Compute::SYNC),
703         std::make_tuple(DriverKind::NEW, Success::PASS_DRIVER, Compute::BURST),
704 
705         std::make_tuple(DriverKind::NEW, Success::PASS_BOTH, Compute::ASYNC),
706         std::make_tuple(DriverKind::NEW, Success::PASS_BOTH, Compute::SYNC),
707         std::make_tuple(DriverKind::NEW, Success::PASS_BOTH, Compute::BURST),
708 
709         std::make_tuple(DriverKind::NEW, Success::FAIL_LAUNCH, Compute::ASYNC),
710         std::make_tuple(DriverKind::NEW, Success::FAIL_LAUNCH, Compute::SYNC),
711         std::make_tuple(DriverKind::NEW, Success::FAIL_LAUNCH, Compute::BURST),
712 
713         // NOTE: Only ASYNC is paired with a wait
714         std::make_tuple(DriverKind::NEW, Success::FAIL_WAIT, Compute::ASYNC));
715 
716 INSTANTIATE_TEST_CASE_P(Flavor, TimingTest, kTimingTestValues);
717 
718 }  // namespace timing_tests
719 
720 /*-- End   timing tests -------------------------------------------------------------------------*/
721 
722 const float kSimpleMultiplier = 2.0f;
723 
createAddMulModel(WrapperModel * model,bool reverseOrder)724 void createAddMulModel(WrapperModel* model, bool reverseOrder) {
725     WrapperOperandType type0(WrapperType::TENSOR_FLOAT32, {2});
726     WrapperOperandType type1(WrapperType::INT32, {});
727     // Phase 1, operands
728     auto op1 = model->addOperand(&type0);
729     auto op2 = model->addOperand(&type0);
730     auto act = model->addOperand(&type1);
731     auto op3 = model->addOperand(&type0);
732     auto op4 = model->addOperand(&type0);
733     auto op5 = model->addOperand(&type0);
734     // Phase 2, operations
735     static int32_t act_init[] = {0};
736     model->setOperandValue(act, act_init, sizeof(act_init));
737     static float multiplier[] = {kSimpleMultiplier, kSimpleMultiplier};
738     model->setOperandValue(op4, multiplier, sizeof(multiplier));
739     if (reverseOrder) {
740         // In this case, add MUL first, but the execution order is still ADD -> MUL.
741         model->addOperation(ANEURALNETWORKS_MUL, {op3, op4, act}, {op5});
742         model->addOperation(ANEURALNETWORKS_ADD, {op1, op2, act}, {op3});
743     } else {
744         model->addOperation(ANEURALNETWORKS_ADD, {op1, op2, act}, {op3});
745         model->addOperation(ANEURALNETWORKS_MUL, {op3, op4, act}, {op5});
746     }
747     // Phase 3, inputs and outputs
748     model->identifyInputsAndOutputs({op1, op2}, {op5});
749     model->finish();
750     ASSERT_TRUE(model->isValid());
751 }
752 
753 // TODO(miaowang): add a test to make sure ANNCompilation_create() has CPU
754 // fallback.
755 // This test verifies that a device that could only handle ADD would correctly report that an
756 // ADD->MUL model could not be fully supported.
TEST_F(IntrospectionControlTest,PartialModelNotSupported)757 TEST_F(IntrospectionControlTest, PartialModelNotSupported) {
758     // This is needed before we have the CPU fallback path being treated as a Device.
759     // TODO(miaowang): remove once b/72506261 is fixed.
760     if (DeviceManager::get()->getUseCpuOnly()) {
761         GTEST_SKIP();
762     }
763 
764     createAddMulModel(&mModel, false);
765 
766     std::string addOnlyDriver = "test-onlyAdd";
767     std::vector<bool> addOnlyOp(android::nn::kNumberOfOperationTypes, false);
768     addOnlyOp[ANEURALNETWORKS_ADD] = true;
769 
770     registerDevices({{addOnlyDriver, 0.9, addOnlyOp}});
771 
772     EXPECT_TRUE(selectDeviceByName(addOnlyDriver));
773     EXPECT_TRUE(isSupportedOpListExpected({true, false}));
774 
775     ANeuralNetworksModel* modelHandle = mModel.getHandle();
776     EXPECT_EQ(ANeuralNetworksCompilation_createForDevices(modelHandle, mDevices.data(),
777                                                           mDevices.size(), &mCompilation),
778               ANEURALNETWORKS_NO_ERROR);
779     // The compilation must fail as there is no fallback when using
780     // Introspection API.
781     EXPECT_NE(ANeuralNetworksCompilation_finish(mCompilation), ANEURALNETWORKS_NO_ERROR);
782 }
783 
784 // This test verifies that a device that could only handle ADD would correctly report that an
785 // ADD->MUL model could not be fully supported. Also verifies that the indices of returned
786 // supported op list correctly map to the order of operations being added by the user.
TEST_F(IntrospectionControlTest,PartialModelNotSupportedOrder)787 TEST_F(IntrospectionControlTest, PartialModelNotSupportedOrder) {
788     // This is needed before we have the CPU fallback path being treated as a Device.
789     // TODO(miaowang): remove once b/72506261 is fixed.
790     if (DeviceManager::get()->getUseCpuOnly()) {
791         GTEST_SKIP();
792     }
793 
794     createAddMulModel(&mModel, true);
795 
796     std::string addOnlyDriver = "test-onlyAdd";
797     std::vector<bool> addOnlyOp(android::nn::kNumberOfOperationTypes, false);
798     addOnlyOp[ANEURALNETWORKS_ADD] = true;
799 
800     registerDevices({{addOnlyDriver, 0.9, addOnlyOp}});
801 
802     EXPECT_TRUE(selectDeviceByName(addOnlyDriver));
803     EXPECT_TRUE(isSupportedOpListExpected({false, true}));
804 }
805 
806 // TODO(miaowang): update the test to make sure the model is actually running on the test devices.
807 // This test verifies that an ADD->MUL model is able to run on two selected devices that together
808 // can handle all operations.
TEST_F(IntrospectionControlTest,ModelNeedTwoDevices)809 TEST_F(IntrospectionControlTest, ModelNeedTwoDevices) {
810     // This is needed before we have the CPU fallback path being treated as a Device.
811     // TODO(miaowang): remove once b/72506261 is fixed.
812     if (DeviceManager::get()->getUseCpuOnly()) {
813         GTEST_SKIP();
814     }
815 
816     createAddMulModel(&mModel, false);
817 
818     std::string addOnlyDriver = "test-onlyAdd";
819     std::vector<bool> addOnlyOp(android::nn::kNumberOfOperationTypes, false);
820     addOnlyOp[ANEURALNETWORKS_ADD] = true;
821 
822     std::string mulOnlyDriver = "test-onlyMul";
823     std::vector<bool> mulOnlyOp(android::nn::kNumberOfOperationTypes, false);
824     mulOnlyOp[ANEURALNETWORKS_MUL] = true;
825 
826     registerDevices({
827             {addOnlyDriver, 0.9, addOnlyOp},
828             {mulOnlyDriver, 0.9, mulOnlyOp},
829     });
830 
831     EXPECT_TRUE(selectDeviceByName(addOnlyDriver));
832     EXPECT_TRUE(selectDeviceByName(mulOnlyDriver));
833     EXPECT_TRUE(isSupportedOpListExpected({true, true}));
834     EXPECT_EQ(prepareForExecution(), ANEURALNETWORKS_NO_ERROR);
835 
836     float input1[2] = {1.0f, 2.0f};
837     float input2[2] = {3.0f, 4.0f};
838     float output[2];
839     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 0, nullptr, input1, sizeof(input1)),
840               ANEURALNETWORKS_NO_ERROR);
841     EXPECT_EQ(ANeuralNetworksExecution_setInput(mExecution, 1, nullptr, input2, sizeof(input2)),
842               ANEURALNETWORKS_NO_ERROR);
843     EXPECT_EQ(ANeuralNetworksExecution_setOutput(mExecution, 0, nullptr, output, sizeof(output)),
844               ANEURALNETWORKS_NO_ERROR);
845 
846     EXPECT_EQ(ANeuralNetworksExecution_startCompute(mExecution, &mEvent), ANEURALNETWORKS_NO_ERROR);
847     EXPECT_EQ(ANeuralNetworksEvent_wait(mEvent), ANEURALNETWORKS_NO_ERROR);
848     EXPECT_EQ(output[0], kSimpleMultiplier * (input1[0] + input2[0]));
849     EXPECT_EQ(output[1], kSimpleMultiplier * (input1[1] + input2[1]));
850 }
851 }  // namespace
852