/* Copyright 2017 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ #include "tensorflow/lite/nnapi/nnapi_implementation.h" #include #include #include #include #include #include #include #include #include "tensorflow/lite/nnapi/sl/public/NeuralNetworksSupportLibraryImpl.h" #ifdef __ANDROID__ #include #endif // __ANDROID__ #define EXPAND_VA_ARGS(...) , ##__VA_ARGS__ #define NNAPI_LOG(format, ...) \ fprintf(stderr, format "\n" EXPAND_VA_ARGS(__VA_ARGS__)); namespace { #ifdef __ANDROID__ // See frameworks/base/core/java/android/os/Process.java in AOSP. const int kFirstIsolatedUid = 99000; const int kLastIsolatedUid = 99999; const int kFirstAppZygoteIsolatedUid = 90000; const int kLastAppZygoteIsolatedUid = 98999; bool IsIsolatedProcess() { int uid = getuid(); return (uid >= kFirstIsolatedUid && uid <= kLastIsolatedUid) || (uid >= kFirstAppZygoteIsolatedUid && uid <= kLastAppZygoteIsolatedUid); } int32_t GetAndroidSdkVersion() { const char* sdkProp = "ro.build.version.sdk"; char sdkVersion[PROP_VALUE_MAX]; int length = __system_property_get(sdkProp, sdkVersion); if (length != 0) { int32_t result = 0; for (int i = 0; i < length; ++i) { int digit = sdkVersion[i] - '0'; if (digit < 0 || digit > 9) { // Non-numeric SDK version, assume it's higher than expected; return 0xffff; } result = result * 10 + digit; } return result; } return 0; } #endif // __ANDROID__ void* LoadFunction(void* handle, const char* name, bool optional) { if (handle == nullptr) { return nullptr; } void* fn = dlsym(handle, name); if (fn == nullptr && !optional) { NNAPI_LOG("nnapi error: unable to open function %s", name); } return fn; } #ifndef __ANDROID__ // Add /dev/shm implementation of shared memory for non-Android platforms int ASharedMemory_create(const char* name, size_t size) { // Each call to ASharedMemory_create produces a unique memory space, hence // name should be unique, otherwise two calls to create memory regions using // the same 'name', will collide. // Caller is responsible to provide a unique name. // Make sure new shared memory region is created: shm_open return an error if // shm object with given name already exists (O_CREAT | O_EXCL) int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); if (fd < 0) { return fd; } int result = ftruncate(fd, size); if (result < 0) { close(fd); return -1; } return fd; } // Determine the NnApi version from loaded entry points uint32_t CalculateAndroidSdkVersion(NnApi const& nnapi) { // Test for specific NNAPI 1.0, 1.1, 1.2 and 1.3 functions bool has_10 = nnapi.ANeuralNetworksMemory_createFromFd != nullptr; bool has_11 = nnapi.ANeuralNetworksModel_relaxComputationFloat32toFloat16 != nullptr; bool has_12 = nnapi.ANeuralNetworks_getDeviceCount != nullptr; bool has_13 = nnapi.ANeuralNetworksCompilation_setTimeout != nullptr; bool has_14 = nnapi.ANeuralNetworks_getRuntimeFeatureLevel != nullptr; uint32_t sdk_version = 0; if (has_10) { sdk_version = 27; } if (sdk_version == 27 && has_11) { sdk_version = 28; } if (sdk_version == 28 && has_12) { sdk_version = 29; } if (sdk_version == 29 && has_13) { sdk_version = 30; } if (sdk_version == 30 && has_14) { sdk_version = 31; } return sdk_version; } #else ASharedMemory_create_fn getASharedMemory_create() { // ASharedMemory_create has different implementations in Android depending on // the partition. Generally it can be loaded from libandroid.so but in vendor // partition (e.g. if a HAL wants to use NNAPI) it is only accessible through // libcutils. void* libandroid = nullptr; libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL); if (libandroid != nullptr) { return reinterpret_cast( LoadFunction(libandroid, "ASharedMemory_create", false)); } std::string libandroid_error = dlerror(); void* cutils_handle = dlopen("libcutils.so", RTLD_LAZY | RTLD_LOCAL); if (cutils_handle != nullptr) { return reinterpret_cast( LoadFunction(cutils_handle, "ashmem_create_region", false)); } NNAPI_LOG( "nnapi error: unable to open both library %s (%s) and library %s " "(%s)", "libandroid.so", libandroid_error.c_str(), "libcutils.so", dlerror()); return nullptr; } #endif // __ANDROID__ #define LOAD_FUNCTION(handle, name) \ nnapi.name = reinterpret_cast( \ LoadFunction(handle, #name, /*optional*/ false)); #define LOAD_FUNCTION_OPTIONAL(handle, name) \ nnapi.name = reinterpret_cast( \ LoadFunction(handle, #name, /*optional*/ true)); #define LOAD_FUNCTION_RENAME(handle, name, symbol) \ nnapi.name = reinterpret_cast( \ LoadFunction(handle, symbol, /*optional*/ false)); const NnApi LoadNnApi() { NnApi nnapi = {}; nnapi.android_sdk_version = 0; #ifdef __ANDROID__ nnapi.android_sdk_version = GetAndroidSdkVersion(); if (nnapi.android_sdk_version < 27) { NNAPI_LOG("nnapi error: requires android sdk version to be at least %d", 27); nnapi.nnapi_exists = false; return nnapi; } // Disable NNAPI for Android 13 and earlier if running in isolated process. if (nnapi.android_sdk_version <= 33 && IsIsolatedProcess()) { NNAPI_LOG("NNAPI is disabled in an isolated process"); nnapi.nnapi_exists = false; return nnapi; } #endif // __ANDROID__ void* libneuralnetworks = nullptr; // TODO(b/123243014): change RTLD_LOCAL? Assumes there can be multiple // instances of nn api RT static const char nnapi_library_name[] = "libneuralnetworks.so"; libneuralnetworks = dlopen(nnapi_library_name, RTLD_LAZY | RTLD_LOCAL); #ifdef __ANDROID__ // Note: If there is an problem trying to open the NNAPI library on a // non-Android system, the error message is suppressed. This is to avoid // showing confusing errors when running in environments that do not support // NNAPI. As more platforms support NNAPI, the #ifdef logic above can be // expanded. if (libneuralnetworks == nullptr) { const char* error = dlerror(); if (error) { NNAPI_LOG("%s\n", error); } NNAPI_LOG("nnapi error: unable to open library %s", nnapi_library_name); } #endif // __ANDROID__ nnapi.nnapi_exists = libneuralnetworks != nullptr; // API 27 (NN 1.0) methods. LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, ANeuralNetworksModel_setOperandSymmPerChannelQuantParams); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromMemory); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_identifyInputsAndOutputs); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutputFromMemory); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait); LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free); #ifdef __ANDROID__ nnapi.ASharedMemory_create = getASharedMemory_create(); #else // Mock ASharedMemory_create only if libneuralnetworks.so was successfully // loaded. This ensures identical behaviour on platforms which use this // implementation, but don't have libneuralnetworks.so library, and // platforms which use nnapi_implementation_disabled.cc stub. if (libneuralnetworks != nullptr) { nnapi.ASharedMemory_create = ASharedMemory_create; } #endif // __ANDROID__ // API 28 (NN 1.1) methods. LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_relaxComputationFloat32toFloat16); // API 29 (NN 1.2) methods. LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDeviceCount); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDevice); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getName); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getVersion); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getFeatureLevel); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getType); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_getSupportedOperationsForDevices); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_createForDevices); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setCaching); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_compute); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandRank); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandDimensions); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_create); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_free); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_burstCompute); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromAHardwareBuffer); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setMeasureTiming); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getDuration); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getExtensionSupport); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_getExtensionOperandType); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_getExtensionOperationType); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandExtensionData); // API 30 (NNAPI 1.3) methods. LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setTimeout); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setPriority); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setTimeout); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setLoopTimeout); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_create); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_free); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addInputRole); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addOutputRole); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_setDimensions); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_finish); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromDesc); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_copy); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_createFromSyncFenceFd); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_getSyncFenceFd); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_startComputeWithDependencies); // API 31 methods LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getRuntimeFeatureLevel); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_enableInputAndOutputPadding); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setReusable); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getSessionId); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getNnApiVersion); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getModelArchHash); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getDeviceIds); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getErrorCode); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getInputDataClass); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getOutputDataClass); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_getCompilationTimeNanos); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_isCachingEnabled); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_isControlFlowUsed); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticCompilationInfo_areDynamicTensorsUsed); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getSessionId); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getNnApiVersion); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getModelArchHash); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getDeviceIds); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getExecutionMode); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getInputDataClass); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getOutputDataClass); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getErrorCode); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getRuntimeExecutionTimeNanos); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getDriverExecutionTimeNanos); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_getHardwareExecutionTimeNanos); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_isCachingEnabled); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_isControlFlowUsed); LOAD_FUNCTION_OPTIONAL( libneuralnetworks, SL_ANeuralNetworksDiagnosticExecutionInfo_areDynamicTensorsUsed); LOAD_FUNCTION_OPTIONAL(libneuralnetworks, SL_ANeuralNetworksDiagnostic_registerCallbacks); #ifndef __ANDROID__ // If libneuralnetworks.so is loaded, but android_sdk_version is not set, // then determine android_sdk_version by testing which functions are // available. if (nnapi.nnapi_exists && nnapi.android_sdk_version == 0) { nnapi.android_sdk_version = CalculateAndroidSdkVersion(nnapi); } #endif // __ANDROID__ // Determin NNAPI Runtime feature level. if (nnapi.ANeuralNetworks_getRuntimeFeatureLevel) { nnapi.nnapi_runtime_feature_level = nnapi.ANeuralNetworks_getRuntimeFeatureLevel(); } else { nnapi.nnapi_runtime_feature_level = nnapi.android_sdk_version; } return nnapi; } } // namespace std::unique_ptr CreateNnApiFromSupportLibrary( const NnApiSLDriverImplFL5* nnapi_support_library_driver) { auto nnapi = std::make_unique(); nnapi->nnapi_exists = true; nnapi->android_sdk_version = ANEURALNETWORKS_FEATURE_LEVEL_5; nnapi->nnapi_runtime_feature_level = nnapi_support_library_driver->base.implFeatureLevel; #define ASSIGN_SL_FUNCTION_TO_NNAPI(name) \ nnapi->name = nnapi_support_library_driver->name; ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromFd); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_create); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_finish); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_addOperand); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandValue); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksModel_setOperandSymmPerChannelQuantParams); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandValueFromMemory); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_addOperation); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_identifyInputsAndOutputs); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksModel_relaxComputationFloat32toFloat16); // ANeuralNetworksCompilation_create is not available in the support library // because its clients are expected to know which accelerator they want to // use. ANeuralNetworksCompilation_createForDevices is available to create // compilation for specified devices. nnapi->ANeuralNetworksCompilation_create = nullptr; ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setPreference); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_finish); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_create); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setInput); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setInputFromMemory); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setOutput); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setOutputFromMemory); // Support library doesn't support regular asynchronous execution. nnapi->ANeuralNetworksExecution_startCompute = nullptr; ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_wait); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_free); #ifdef __ANDROID__ nnapi->ASharedMemory_create = getASharedMemory_create(); #else nnapi->ASharedMemory_create = ASharedMemory_create; #endif // __ANDROID__ ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getDeviceCount); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getDevice); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getName); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getVersion); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getFeatureLevel); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getType); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksModel_getSupportedOperationsForDevices); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_createForDevices); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setCaching); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setTimeout); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksCompilation_setPriority); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_compute); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setTimeout); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setLoopTimeout); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_getOutputOperandRank); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksExecution_getOutputOperandDimensions); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksBurst_create); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksBurst_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_burstCompute); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromAHardwareBuffer); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setMeasureTiming); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_getDuration); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksDevice_getExtensionSupport); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_getExtensionOperandType); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_getExtensionOperationType); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksModel_setOperandExtensionData); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_create); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_free); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_addInputRole); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_addOutputRole); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_setDimensions); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemoryDesc_finish); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_createFromDesc); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksMemory_copy); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_createFromSyncFenceFd); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksEvent_getSyncFenceFd); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksExecution_startComputeWithDependencies); ASSIGN_SL_FUNCTION_TO_NNAPI( ANeuralNetworksExecution_enableInputAndOutputPadding); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworksExecution_setReusable); ASSIGN_SL_FUNCTION_TO_NNAPI(ANeuralNetworks_getRuntimeFeatureLevel); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getSessionId); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getNnApiVersion); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getModelArchHash); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getDeviceIds); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getErrorCode); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getInputDataClass); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getOutputDataClass); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_getCompilationTimeNanos); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_isCachingEnabled); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_isControlFlowUsed); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticCompilationInfo_areDynamicTensorsUsed); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getSessionId); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getNnApiVersion); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getModelArchHash); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getDeviceIds); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getExecutionMode); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getInputDataClass); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getOutputDataClass); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getErrorCode); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getRuntimeExecutionTimeNanos); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getDriverExecutionTimeNanos); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_getHardwareExecutionTimeNanos); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_isCachingEnabled); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_isControlFlowUsed); ASSIGN_SL_FUNCTION_TO_NNAPI( SL_ANeuralNetworksDiagnosticExecutionInfo_areDynamicTensorsUsed); ASSIGN_SL_FUNCTION_TO_NNAPI(SL_ANeuralNetworksDiagnostic_registerCallbacks); // There are several functions that are defined in the SL but are not yet used // in the delegate: // * ANeuralNetworksDevice_wait // * ANeuralNetworksModel_setOperandValueFromModel // * ANeuralNetworks_getDefaultLoopTimeout // * ANeuralNetworks_getMaximumLoopTimeout return nnapi; } const NnApi* NnApiImplementation() { static const NnApi nnapi = LoadNnApi(); return &nnapi; }