/* * Copyright (C) 2021 The Android Open Source Project * * 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. */ #define LOG_TAG "NeuralNetworksShim" #include "NeuralNetworksShim.h" #include #include #include #include #include #include #include "ShimDevice.h" #include "ShimDeviceManager.h" static_assert(offsetof(NnApiSLDriverImplFL5, base.implFeatureLevel) == 0, ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL5 struct"); static_assert(offsetof(NnApiSLDriverImplFL6, base.implFeatureLevel) == 0, ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL6 struct"); static_assert(offsetof(NnApiSLDriverImplFL7, base.implFeatureLevel) == 0, ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL7 struct"); static_assert(offsetof(NnApiSLDriverImplFL8, base) == 0, ".base is not at offset 0 of a NnApiSLDriverImplFL8 struct"); static_assert(offsetof(NnApiSLDriverImplFL8, base.base) == 0, ".base.base is not at offset 0 of a NnApiSLDriverImplFL8 struct"); static_assert(offsetof(NnApiSLDriverImplFL8, base.base.implFeatureLevel) == 0, ".base.base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL8 struct"); static_assert(offsetof(NnApiSLDriverImpl, implFeatureLevel) == 0, ".implFeatureLevel is not at offset 0 of a NnApiSLDriverImpl struct"); static_assert(sizeof(NnApiSLDriverImpl) == sizeof(int64_t), "NnApiSLDriverImpl size changed"); // NOTE: NnApiSLDriverImplFL5 is currently aligned to 8 bytes. In prior versions of the Support // Library interface, we added a "reserved_placeholder" to force alignment on 32-bit platforms. This // may need to be done in the future if this struct again becomes unaligned. This would look like: // /** // * Extra pointer required to align to 8 bytes on 32bit archs. // */ // void (*reserved_placeholder1)(); static_assert(sizeof(NnApiSLDriverImplFL5) == sizeof(int64_t) + 104 * sizeof(void*), "NnApiSLDriverImplFL5 size changed"); static_assert(sizeof(NnApiSLDriverImplFL6) == sizeof(int64_t) + 104 * sizeof(void*), "NnApiSLDriverImplFL6 size changed"); static_assert(sizeof(NnApiSLDriverImplFL7) == sizeof(int64_t) + 104 * sizeof(void*), "NnApiSLDriverImplFL7 size changed"); static_assert(sizeof(NnApiSLDriverImplFL8) == sizeof(NnApiSLDriverImplFL7) + 2 * sizeof(void*), "NnApiSLDriverImplFL8 size changed"); static_assert(ANNSHIM_NO_ERROR == 0, "ANNSHIM_NO_ERROR has changed"); static_assert(ANNSHIM_FAILED_TO_LOAD_SL == 1, "ANNSHIM_FAILED_TO_LOAD_SL has changed"); static_assert(ANNSHIM_FAILED_TO_REGISTER_SERVICE == 2, "ANNSHIM_FAILED_TO_REGISTER_SERVICE has changed"); static_assert(ANNSHIM_GENERAL_ERROR == 3, "ANNSHIM_GENERAL_ERROR has changed"); static_assert(ANNSHIM_INVALID_ARGUMENT == 4, "ANNSHIM_INVALID_ARGUMENT has changed"); using android::neuralnetworks::shim::registerDevices; using android::neuralnetworks::shim::RegistrationParams; using android::neuralnetworks::shim::ShimDeviceInfo; int ANeuralNetworksShim_registerSupportLibraryService( const ANeuralNetworksShimRegistrationParams* registrationParams) { if (registrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, registrationParams == nullptr "; return ANNSHIM_INVALID_ARGUMENT; } const auto* params = reinterpret_cast(registrationParams); NnApiSLDriverImpl* const nnapiImpl = params->nnapiSupportLibraryPackage; const auto& deviceInfos = params->deviceInfos; const uint32_t numberOfListenerThreads = params->numberOfListenerThreads; const bool registerAsLazyService = params->registerAsLazyService; const bool fallbackToMinimumSupportDevice = params->fallbackToMinimumSupportDevice; return static_cast(registerDevices(nnapiImpl, deviceInfos, numberOfListenerThreads, registerAsLazyService, fallbackToMinimumSupportDevice)); } int ANeuralNetworksShimDeviceInfo_create(ANeuralNetworksShimDeviceInfo** deviceInfo, const char* deviceName, const char* serviceName) { if (deviceInfo != nullptr) { *deviceInfo = nullptr; } if (deviceName == nullptr) { LOG(ERROR) << "Invalid arguments, deviceName passed a nullptr"; return ANNSHIM_INVALID_ARGUMENT; } auto result = new (std::nothrow) ShimDeviceInfo{.deviceName = std::string(deviceName), .serviceName = (serviceName == nullptr || strlen(serviceName) == 0) ? std::string(deviceName) : std::string(serviceName)}; if (result == nullptr) { return ANNSHIM_GENERAL_ERROR; } *deviceInfo = reinterpret_cast(result); return ANNSHIM_NO_ERROR; } void ANeuralNetworksShimDeviceInfo_free(ANeuralNetworksShimDeviceInfo* deviceInfo) { delete reinterpret_cast(deviceInfo); } int ANeuralNetworksShimRegistrationParams_create( NnApiSLDriverImpl* nnapiSupportLibraryPackage, ANeuralNetworksShimRegistrationParams** outRegistrationParams) { if (outRegistrationParams != nullptr) { *outRegistrationParams = nullptr; } if (nnapiSupportLibraryPackage == nullptr) { LOG(ERROR) << "Invalid arguments, nnapiSupportLibraryPackage == nullptr "; return ANNSHIM_INVALID_ARGUMENT; } if (outRegistrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, outRegistrationParams == nullptr "; return ANNSHIM_INVALID_ARGUMENT; } auto result = new (std::nothrow) RegistrationParams{ .nnapiSupportLibraryPackage = nnapiSupportLibraryPackage, .registerAsLazyService = false, .fallbackToMinimumSupportDevice = false, }; if (result == nullptr) { return ANNSHIM_GENERAL_ERROR; } *outRegistrationParams = reinterpret_cast(result); return ANNSHIM_NO_ERROR; } void ANeuralNetworksShimRegistrationParams_free( ANeuralNetworksShimRegistrationParams* registrationParams) { delete reinterpret_cast(registrationParams); } int ANeuralNetworksShimRegistrationParams_addDeviceInfo( ANeuralNetworksShimRegistrationParams* registrationParams, const ANeuralNetworksShimDeviceInfo* deviceInfo) { if (registrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, registrationParams == nullptr"; return ANNSHIM_INVALID_ARGUMENT; } if (deviceInfo == nullptr) { LOG(ERROR) << "Invalid arguments, deviceInfo == nullptr"; return ANNSHIM_INVALID_ARGUMENT; } auto params = reinterpret_cast(registrationParams); auto info = reinterpret_cast(deviceInfo); params->deviceInfos.push_back(*info); return ANNSHIM_NO_ERROR; } int ANeuralNetworksShimRegistrationParams_setNumberOfListenerThreads( ANeuralNetworksShimRegistrationParams* registrationParams, uint32_t numberOfListenerThreads) { if (registrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, registrationParams == nullptr"; return ANNSHIM_INVALID_ARGUMENT; } if (registrationParams == 0) { LOG(ERROR) << "Invalid arguments, numberOfListenerThreads == 0"; return ANNSHIM_INVALID_ARGUMENT; } auto params = reinterpret_cast(registrationParams); params->numberOfListenerThreads = numberOfListenerThreads; return ANNSHIM_NO_ERROR; } int ANeuralNetworksShimRegistrationParams_registerAsLazyService( ANeuralNetworksShimRegistrationParams* registrationParams, bool asLazy) { if (registrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, registrationParams == nullptr"; return ANNSHIM_INVALID_ARGUMENT; } auto params = reinterpret_cast(registrationParams); params->registerAsLazyService = asLazy; return ANNSHIM_NO_ERROR; } int ANeuralNetworksShimRegistrationParams_fallbackToMinimumSupportDevice( ANeuralNetworksShimRegistrationParams* registrationParams, bool fallback) { if (registrationParams == nullptr) { LOG(ERROR) << "Invalid arguments, registrationParams == nullptr"; return ANNSHIM_INVALID_ARGUMENT; } auto params = reinterpret_cast(registrationParams); params->fallbackToMinimumSupportDevice = fallback; return ANNSHIM_NO_ERROR; }