1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include "tensorflow/lite/nnapi/nnapi_implementation.h"
16
17 #include <dlfcn.h>
18 #include <fcntl.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22
23 #include <algorithm>
24 #include <cstdlib>
25
26 #include "tensorflow/lite/nnapi/NeuralNetworksTypes.h"
27 #include "tensorflow/lite/nnapi/sl/public/NeuralNetworksSupportLibraryImpl.h"
28
29 #ifdef __ANDROID__
30 #include <sys/system_properties.h>
31 #endif // __ANDROID__
32
33 #define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__);
34
35 namespace {
36
37 #ifdef __ANDROID__
GetAndroidSdkVersion()38 int32_t GetAndroidSdkVersion() {
39 const char* sdkProp = "ro.build.version.sdk";
40 char sdkVersion[PROP_VALUE_MAX];
41 int length = __system_property_get(sdkProp, sdkVersion);
42 if (length != 0) {
43 int32_t result = 0;
44 for (int i = 0; i < length; ++i) {
45 int digit = sdkVersion[i] - '0';
46 if (digit < 0 || digit > 9) {
47 // Non-numeric SDK version, assume it's higher than expected;
48 return 0xffff;
49 }
50 result = result * 10 + digit;
51 }
52 return result;
53 }
54 return 0;
55 }
56 #endif // __ANDROID__
57
LoadFunction(void * handle,const char * name,bool optional)58 void* LoadFunction(void* handle, const char* name, bool optional) {
59 if (handle == nullptr) {
60 return nullptr;
61 }
62 void* fn = dlsym(handle, name);
63 if (fn == nullptr && !optional) {
64 NNAPI_LOG("nnapi error: unable to open function %s", name);
65 }
66 return fn;
67 }
68
69 #ifndef __ANDROID__
70 // Add /dev/shm implementation of shared memory for non-Android platforms
ASharedMemory_create(const char * name,size_t size)71 int ASharedMemory_create(const char* name, size_t size) {
72 // Each call to ASharedMemory_create produces a unique memory space, hence
73 // name should be unique, otherwise two calls to create memory regions using
74 // the same 'name', will collide.
75 // Caller is responsible to provide a unique name.
76
77 // Make sure new shared memory region is created: shm_open return an error if
78 // shm object with given name already exists (O_CREAT | O_EXCL)
79 int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0644);
80 if (fd < 0) {
81 return fd;
82 }
83 int result = ftruncate(fd, size);
84 if (result < 0) {
85 close(fd);
86 return -1;
87 }
88 return fd;
89 }
90
91 // Determine the NnApi version from loaded entry points
CalculateAndroidSdkVersion(NnApi const & nnapi)92 uint32_t CalculateAndroidSdkVersion(NnApi const& nnapi) {
93 // Test for specific NNAPI 1.0, 1.1, 1.2 and 1.3 functions
94 bool has_10 = nnapi.ANeuralNetworksMemory_createFromFd != nullptr;
95 bool has_11 =
96 nnapi.ANeuralNetworksModel_relaxComputationFloat32toFloat16 != nullptr;
97 bool has_12 = nnapi.ANeuralNetworks_getDeviceCount != nullptr;
98 bool has_13 = nnapi.ANeuralNetworksCompilation_setTimeout != nullptr;
99 bool has_14 = nnapi.ANeuralNetworks_getRuntimeFeatureLevel != nullptr;
100
101 uint32_t sdk_version = 0;
102 if (has_10) {
103 sdk_version = 27;
104 }
105 if (sdk_version == 27 && has_11) {
106 sdk_version = 28;
107 }
108 if (sdk_version == 28 && has_12) {
109 sdk_version = 29;
110 }
111 if (sdk_version == 29 && has_13) {
112 sdk_version = 30;
113 }
114 if (sdk_version == 30 && has_14) {
115 sdk_version = 31;
116 }
117 return sdk_version;
118 }
119 #else
120
getASharedMemory_create()121 ASharedMemory_create_fn getASharedMemory_create() {
122 // ASharedMemory_create has different implementations in Android depending on
123 // the partition. Generally it can be loaded from libandroid.so but in vendor
124 // partition (e.g. if a HAL wants to use NNAPI) it is only accessible through
125 // libcutils.
126 void* libandroid = nullptr;
127 libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
128 if (libandroid != nullptr) {
129 return reinterpret_cast<ASharedMemory_create_fn>(
130 LoadFunction(libandroid, "ASharedMemory_create", false));
131 }
132
133 std::string libandroid_error = dlerror();
134 void* cutils_handle = dlopen("libcutils.so", RTLD_LAZY | RTLD_LOCAL);
135 if (cutils_handle != nullptr) {
136 return reinterpret_cast<ASharedMemory_create_fn>(
137 LoadFunction(cutils_handle, "ashmem_create_region", false));
138 }
139
140 NNAPI_LOG(
141 "nnapi error: unable to open both library %s (%s) and library %s "
142 "(%s)",
143 "libandroid.so", libandroid_error.c_str(), "libcutils.so", dlerror());
144 return nullptr;
145 }
146
147 #endif // __ANDROID__
148
149 #define LOAD_FUNCTION(handle, name) \
150 nnapi.name = reinterpret_cast<name##_fn>( \
151 LoadFunction(handle, #name, /*optional*/ false));
152
153 #define LOAD_FUNCTION_OPTIONAL(handle, name) \
154 nnapi.name = reinterpret_cast<name##_fn>( \
155 LoadFunction(handle, #name, /*optional*/ true));
156
157 #define LOAD_FUNCTION_RENAME(handle, name, symbol) \
158 nnapi.name = reinterpret_cast<name##_fn>( \
159 LoadFunction(handle, symbol, /*optional*/ false));
160
LoadNnApi()161 const NnApi LoadNnApi() {
162 NnApi nnapi = {};
163 nnapi.android_sdk_version = 0;
164
165 #ifdef __ANDROID__
166 nnapi.android_sdk_version = GetAndroidSdkVersion();
167 if (nnapi.android_sdk_version < 27) {
168 NNAPI_LOG("nnapi error: requires android sdk version to be at least %d",
169 27);
170 nnapi.nnapi_exists = false;
171 return nnapi;
172 }
173 #endif // __ANDROID__
174
175 void* libneuralnetworks = nullptr;
176 // TODO(b/123243014): change RTLD_LOCAL? Assumes there can be multiple
177 // instances of nn api RT
178 static const char nnapi_library_name[] = "libneuralnetworks.so";
179 libneuralnetworks = dlopen(nnapi_library_name, RTLD_LAZY | RTLD_LOCAL);
180 #ifdef __ANDROID__
181 // Note: If there is an problem trying to open the NNAPI library on a
182 // non-Android system, the error message is suppressed. This is to avoid
183 // showing confusing errors when running in environments that do not support
184 // NNAPI. As more platforms support NNAPI, the #ifdef logic above can be
185 // expanded.
186 if (libneuralnetworks == nullptr) {
187 const char* error = dlerror();
188 if (error) {
189 NNAPI_LOG("%s\n", error);
190 }
191 NNAPI_LOG("nnapi error: unable to open library %s", nnapi_library_name);
192 }
193 #endif // __ANDROID__
194
195 nnapi.nnapi_exists = libneuralnetworks != nullptr;
196
197 // API 27 (NN 1.0) methods.
198 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd);
199 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free);
200 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create);
201 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free);
202 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish);
203 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand);
204 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue);
205 LOAD_FUNCTION_OPTIONAL(
206 libneuralnetworks,
207 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
208 LOAD_FUNCTION(libneuralnetworks,
209 ANeuralNetworksModel_setOperandValueFromMemory);
210 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation);
211 LOAD_FUNCTION(libneuralnetworks,
212 ANeuralNetworksModel_identifyInputsAndOutputs);
213 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create);
214 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free);
215 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference);
216 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish);
217 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create);
218 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free);
219 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput);
220 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory);
221 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput);
222 LOAD_FUNCTION(libneuralnetworks,
223 ANeuralNetworksExecution_setOutputFromMemory);
224 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute);
225 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait);
226 LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free);
227
228 #ifdef __ANDROID__
229 nnapi.ASharedMemory_create = getASharedMemory_create();
230 #else
231 // Mock ASharedMemory_create only if libneuralnetworks.so was successfully
232 // loaded. This ensures identical behaviour on platforms which use this
233 // implementation, but don't have libneuralnetworks.so library, and
234 // platforms which use nnapi_implementation_disabled.cc stub.
235 if (libneuralnetworks != nullptr) {
236 nnapi.ASharedMemory_create = ASharedMemory_create;
237 }
238 #endif // __ANDROID__
239
240 // API 28 (NN 1.1) methods.
241 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
242 ANeuralNetworksModel_relaxComputationFloat32toFloat16);
243
244 // API 29 (NN 1.2) methods.
245 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDeviceCount);
246 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDevice);
247 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getName);
248 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getVersion);
249 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
250 ANeuralNetworksDevice_getFeatureLevel);
251 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getType);
252 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
253 ANeuralNetworksModel_getSupportedOperationsForDevices);
254 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
255 ANeuralNetworksCompilation_createForDevices);
256 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
257 ANeuralNetworksCompilation_setCaching);
258 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_compute);
259 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
260 ANeuralNetworksExecution_getOutputOperandRank);
261 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
262 ANeuralNetworksExecution_getOutputOperandDimensions);
263 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_create);
264 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_free);
265 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
266 ANeuralNetworksExecution_burstCompute);
267 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
268 ANeuralNetworksMemory_createFromAHardwareBuffer);
269 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
270 ANeuralNetworksExecution_setMeasureTiming);
271 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
272 ANeuralNetworksExecution_getDuration);
273 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
274 ANeuralNetworksDevice_getExtensionSupport);
275 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
276 ANeuralNetworksModel_getExtensionOperandType);
277 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
278 ANeuralNetworksModel_getExtensionOperationType);
279 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
280 ANeuralNetworksModel_setOperandExtensionData);
281
282 // API 30 (NNAPI 1.3) methods.
283 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
284 ANeuralNetworksCompilation_setTimeout);
285 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
286 ANeuralNetworksCompilation_setPriority);
287 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
288 ANeuralNetworksExecution_setTimeout);
289 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
290 ANeuralNetworksExecution_setLoopTimeout);
291 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_create);
292 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_free);
293 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
294 ANeuralNetworksMemoryDesc_addInputRole);
295 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
296 ANeuralNetworksMemoryDesc_addOutputRole);
297 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
298 ANeuralNetworksMemoryDesc_setDimensions);
299 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_finish);
300 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
301 ANeuralNetworksMemory_createFromDesc);
302 LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_copy);
303 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
304 ANeuralNetworksEvent_createFromSyncFenceFd);
305 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
306 ANeuralNetworksEvent_getSyncFenceFd);
307 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
308 ANeuralNetworksExecution_startComputeWithDependencies);
309
310 // API 31 methods
311 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
312 ANeuralNetworks_getRuntimeFeatureLevel);
313 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
314 ANeuralNetworksExecution_enableInputAndOutputPadding);
315 LOAD_FUNCTION_OPTIONAL(libneuralnetworks,
316 ANeuralNetworksExecution_setReusable);
317 #ifndef __ANDROID__
318 // If libneuralnetworks.so is loaded, but android_sdk_version is not set,
319 // then determine android_sdk_version by testing which functions are
320 // available.
321 if (nnapi.nnapi_exists && nnapi.android_sdk_version == 0) {
322 nnapi.android_sdk_version = CalculateAndroidSdkVersion(nnapi);
323 }
324 #endif // __ANDROID__
325 // Determin NNAPI Runtime feature level.
326 if (nnapi.ANeuralNetworks_getRuntimeFeatureLevel) {
327 nnapi.nnapi_runtime_feature_level =
328 nnapi.ANeuralNetworks_getRuntimeFeatureLevel();
329 } else {
330 nnapi.nnapi_runtime_feature_level = nnapi.android_sdk_version;
331 }
332
333 return nnapi;
334 }
335
336 } // namespace
337
CreateNnApiFromSupportLibrary(const NnApiSLDriverImplFL5 * nnapi_support_library_driver)338 std::unique_ptr<const NnApi> CreateNnApiFromSupportLibrary(
339 const NnApiSLDriverImplFL5* nnapi_support_library_driver) {
340 auto nnapi = std::make_unique<NnApi>();
341 nnapi->nnapi_exists = true;
342 nnapi->android_sdk_version = ANEURALNETWORKS_FEATURE_LEVEL_5;
343 nnapi->nnapi_runtime_feature_level =
344 nnapi_support_library_driver->base.implFeatureLevel;
345
346 #define ASSIGN_SL_FUNCTION_TO_NNAPI(name) \
347 nnapi->name = nnapi_support_library_driver->name;
348
349 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromFd);
350 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_free);
351 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_create);
352 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_free);
353 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_finish);
354 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_addOperand);
355 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandValue);
356 ASSIGN_SL_FUNCTION_TO_NNAPI(
357 ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
358 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandValueFromMemory);
359 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_addOperation);
360 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_identifyInputsAndOutputs);
361 ASSIGN_SL_FUNCTION_TO_NNAPI(
362 ANeuralNetworksModel_relaxComputationFloat32toFloat16);
363 // ANeuralNetworksCompilation_create is not available in the support library
364 // because its clients are expected to know which accelerator they want to
365 // use. ANeuralNetworksCompilation_createForDevices is available to create
366 // compilation for specified devices.
367 nnapi->ANeuralNetworksCompilation_create = nullptr;
368 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_free);
369 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setPreference);
370 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_finish);
371 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_create);
372 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_free);
373 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setInput);
374 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setInputFromMemory);
375 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setOutput);
376 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setOutputFromMemory);
377 // Support library doesn't support regular asynchronous execution.
378 nnapi->ANeuralNetworksExecution_startCompute = nullptr;
379 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_wait);
380 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_free);
381
382 #ifdef __ANDROID__
383 nnapi->ASharedMemory_create = getASharedMemory_create();
384 #else
385 nnapi->ASharedMemory_create = ASharedMemory_create;
386 #endif // __ANDROID__
387
388 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getDeviceCount);
389 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getDevice);
390 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getName);
391 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getVersion);
392 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getFeatureLevel);
393 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getType);
394 ASSIGN_SL_FUNCTION_TO_NNAPI(
395 ANeuralNetworksModel_getSupportedOperationsForDevices);
396 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_createForDevices);
397 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setCaching);
398 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setTimeout);
399 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setPriority);
400 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_compute);
401 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setTimeout);
402 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setLoopTimeout);
403 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_getOutputOperandRank);
404 ASSIGN_SL_FUNCTION_TO_NNAPI(
405 ANeuralNetworksExecution_getOutputOperandDimensions);
406 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksBurst_create);
407 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksBurst_free);
408 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_burstCompute);
409 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromAHardwareBuffer);
410 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setMeasureTiming);
411 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_getDuration);
412 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getExtensionSupport);
413 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_getExtensionOperandType);
414 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_getExtensionOperationType);
415 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandExtensionData);
416
417 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_create);
418 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_free);
419 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_addInputRole);
420 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_addOutputRole);
421 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_setDimensions);
422 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_finish);
423
424 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromDesc);
425 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_copy);
426
427 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_createFromSyncFenceFd);
428 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_getSyncFenceFd);
429
430 ASSIGN_SL_FUNCTION_TO_NNAPI(
431 ANeuralNetworksExecution_startComputeWithDependencies);
432 ASSIGN_SL_FUNCTION_TO_NNAPI(
433 ANeuralNetworksExecution_enableInputAndOutputPadding);
434 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setReusable);
435
436 ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getRuntimeFeatureLevel);
437
438 // There are several functions that are defined in the SL but are not yet used
439 // in the delegate:
440 // * ANeuralNetworksDevice_wait
441 // * ANeuralNetworksModel_setOperandValueFromModel
442 // * ANeuralNetworks_getDefaultLoopTimeout
443 // * ANeuralNetworks_getMaximumLoopTimeout
444
445 return nnapi;
446 }
447
NnApiImplementation()448 const NnApi* NnApiImplementation() {
449 static const NnApi nnapi = LoadNnApi();
450 return &nnapi;
451 }
452