|
- /* 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 <dnnlibrary/nnapi_implementation.h>
-
- #include <dlfcn.h>
- #include <fcntl.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <unistd.h>
-
- #include <cstdlib>
-
- #ifdef __ANDROID__
- #include <sys/system_properties.h>
- #endif // __ANDROID__
-
- #define NNAPI_LOG(format, ...) fprintf(stderr, format "\n", __VA_ARGS__);
-
- #ifdef __ANDROID__
- 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;
- }
- // TODO(levp): remove once SDK gets updated to 29th level
- // Upgrade SDK version for pre-release Q to be able to test functionality
- // available from SDK level 29.
- if (result == 28) {
- char versionCodename[PROP_VALUE_MAX];
- const char* versionCodenameProp = "ro.build.version.codename";
- length = __system_property_get(versionCodenameProp, versionCodename);
- if (length != 0) {
- if (versionCodename[0] == 'Q') {
- return 29;
- }
- }
- }
- return result;
- }
- return 0;
- }
- #endif // __ANDROID__
-
- namespace {
-
- 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) {
- int fd = shm_open(name, O_RDWR | O_CREAT, 0644);
- if (fd < 0) {
- return fd;
- }
- int result = ftruncate(fd, size);
- if (result < 0) {
- close(fd);
- return -1;
- }
- return fd;
- }
- #endif // __ANDROID__
-
- #define LOAD_FUNCTION(handle, name) \
- nnapi.name = reinterpret_cast<name##_fn>( \
- LoadFunction(handle, #name, /*optional*/ false));
-
- #define LOAD_FUNCTION_OPTIONAL(handle, name) \
- nnapi.name = reinterpret_cast<name##_fn>( \
- LoadFunction(handle, #name, /*optional*/ true));
-
- #define LOAD_FUNCTION_RENAME(handle, name, symbol) \
- nnapi.name = reinterpret_cast<name##_fn>( \
- 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;
- }
- #endif // __ANDROID__
-
- void* libneuralnetworks = nullptr;
- // TODO(b/123243014): change RTLD_LOCAL? Assumes there can be multiple
- // instances of nn api RT
- libneuralnetworks = dlopen("libneuralnetworks.so", RTLD_LAZY | RTLD_LOCAL);
- if (libneuralnetworks == nullptr) {
- NNAPI_LOG("nnapi error: unable to open library %s", "libneuralnetworks.so");
- }
-
- 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);
-
- // 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.
- #ifdef __ANDROID__
- void* libandroid = nullptr;
- libandroid = dlopen("libandroid.so", RTLD_LAZY | RTLD_LOCAL);
- if (libandroid != nullptr) {
- LOAD_FUNCTION(libandroid, ASharedMemory_create);
- } else {
- void* cutils_handle = dlopen("libcutils.so", RTLD_LAZY | RTLD_LOCAL);
- if (cutils_handle != nullptr) {
- LOAD_FUNCTION_RENAME(cutils_handle, ASharedMemory_create,
- "ashmem_create_region");
- } else {
- NNAPI_LOG("nnapi error: unable to open neither libraries %s and %s",
- "libandroid.so", "libcutils.so");
- }
- }
- #else
- 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);
- return nnapi;
- }
-
- } // namespace
-
- const NnApi* NnApiImplementation() {
- static const NnApi nnapi = LoadNnApi();
- return &nnapi;
- }
|