1 /**
2 * Copyright 2022 Huawei Technologies Co., Ltd
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 "src/litert/delegate/nnapi/nnapi_implementation.h"
18 #include <dlfcn.h>
19 #include <fcntl.h>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22 #include <sys/system_properties.h>
23 #include <unistd.h>
24 #include <string>
25 #include <algorithm>
26 #include <cstdlib>
27 #include "src/common/log_adapter.h"
28 #include "include/errorcode.h"
29
30 namespace mindspore {
31 namespace lite {
32 namespace {
GetAndroidSdkVersion()33 int32_t GetAndroidSdkVersion() {
34 const char *sdk_prop = "ro.build.version.sdk";
35 char prop_value[PROP_VALUE_MAX];
36 (void)__system_property_get(sdk_prop, prop_value);
37 std::function<bool(const std::string)> is_valid_num = [](const std::string &str) {
38 return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
39 };
40 int sdk_version = 0;
41 if (is_valid_num(std::string(prop_value))) {
42 sdk_version = std::stoi(std::string(prop_value));
43 }
44 return sdk_version;
45 }
46
LoadNNAPIFunction(void * handle,const char * name,bool optional)47 void *LoadNNAPIFunction(void *handle, const char *name, bool optional) {
48 if (handle == nullptr) {
49 return nullptr;
50 }
51 void *fn = dlsym(handle, name);
52 if (fn == nullptr && !optional) {
53 MS_LOG(ERROR) << "Load NNAPI function failed: " << name;
54 }
55 return fn;
56 }
57
58 #define LOAD_NNAPI_FUNCTION(handle, name) \
59 nnapi.name = reinterpret_cast<name##_fn>(LoadNNAPIFunction(handle, #name, false));
60
61 #define LOAD_NNAPI_FUNCTION_OPTIONAL(handle, name) \
62 nnapi.name = reinterpret_cast<name##_fn>(LoadNNAPIFunction(handle, #name, true));
63
LoadNNAPI()64 const NNAPI LoadNNAPI() {
65 NNAPI nnapi = {};
66 nnapi.android_sdk_version = 0;
67
68 void *libneuralnetworks = nullptr;
69 // instances of nn api RT
70 auto get_dl_error = []() -> std::string {
71 auto error = dlerror();
72 return error == nullptr ? "" : error;
73 };
74 static const char nnapi_library_name[] = "libneuralnetworks.so";
75 libneuralnetworks = dlopen(nnapi_library_name, RTLD_LAZY | RTLD_LOCAL);
76 if (libneuralnetworks == nullptr) {
77 auto error = get_dl_error();
78 MS_LOG(ERROR) << "dlopen " << nnapi_library_name << " failed, error: " << error;
79 nnapi.nnapi_exists = false;
80 return nnapi;
81 }
82 nnapi.nnapi_exists = true;
83 nnapi.android_sdk_version = GetAndroidSdkVersion();
84 if (nnapi.android_sdk_version < ANEURALNETWORKS_FEATURE_LEVEL_1) {
85 MS_LOG(ERROR) << "Android NNAPI requires android sdk version to be at least 27";
86 nnapi.nnapi_exists = false;
87 return nnapi;
88 }
89
90 // NNAPI level 1 (API 27) methods.
91 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd);
92 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free);
93 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create);
94 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free);
95 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish);
96 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand);
97 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue);
98 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromMemory);
99 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation);
100 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_identifyInputsAndOutputs);
101 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create);
102 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free);
103 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference);
104 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish);
105 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create);
106 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free);
107 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput);
108 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory);
109 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput);
110 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutputFromMemory);
111 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute);
112 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait);
113 LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free);
114
115 // NNAPI level 2 (API 28) methods.
116 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_relaxComputationFloat32toFloat16);
117
118 // NNAPI level 3 (API 29) methods.
119 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDeviceCount);
120 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDevice);
121 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getName);
122 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getType);
123 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getVersion);
124 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getFeatureLevel);
125 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_getSupportedOperationsForDevices);
126 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_createForDevices);
127 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setCaching);
128 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_compute);
129 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandRank);
130 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandDimensions);
131 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_create);
132 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_free);
133 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_burstCompute);
134 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromAHardwareBuffer);
135 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setMeasureTiming);
136 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getDuration);
137 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
138
139 // NNAPI level 4 (API 30) methods.
140 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_create);
141 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_free);
142 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addInputRole);
143 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addOutputRole);
144 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_setDimensions);
145 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_finish);
146 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromDesc);
147 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_copy);
148 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_wait);
149 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromModel);
150 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setPriority);
151 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setTimeout);
152 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setTimeout);
153 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setLoopTimeout);
154 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDefaultLoopTimeout);
155 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getMaximumLoopTimeout);
156 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_createFromSyncFenceFd);
157 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_getSyncFenceFd);
158 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_startComputeWithDependencies);
159
160 // NNAPI level 5 (API 31) methods.
161 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getRuntimeFeatureLevel);
162 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_enableInputAndOutputPadding);
163 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryAlignmentForInput);
164 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryPaddingForInput);
165 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryAlignmentForOutput);
166 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryPaddingForOutput);
167 LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setReusable);
168
169 return nnapi;
170 }
171 } // namespace
172
NNAPIImplementation()173 const NNAPI *NNAPIImplementation() {
174 static const NNAPI nnapi = LoadNNAPI();
175 return &nnapi;
176 }
177 } // namespace lite
178 } // namespace mindspore
179