1 /*
2 * Copyright (C) 2021 The Android Open Source Project
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 #define LOG_TAG "NeuralNetworksShim"
18
19 #include "NeuralNetworksShim.h"
20
21 #include <android-base/logging.h>
22 #include <nnapi/Types.h>
23
24 #include <limits>
25 #include <string>
26 #include <utility>
27 #include <vector>
28
29 #include "ShimDevice.h"
30 #include "ShimDeviceManager.h"
31
32 static_assert(offsetof(NnApiSLDriverImplFL5, base.implFeatureLevel) == 0,
33 ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL5 struct");
34 static_assert(offsetof(NnApiSLDriverImpl, implFeatureLevel) == 0,
35 ".implFeatureLevel is not at offset 0 of a NnApiSLDriverImpl struct");
36
37 static_assert(sizeof(NnApiSLDriverImpl) == sizeof(int64_t), "NnApiSLDriverImpl size changed");
38
39 // 71 real ones and 1 synthetic placeholder to algin to 8 bytes on 32 bit archs
40 static_assert(sizeof(NnApiSLDriverImplFL5) == sizeof(int64_t) + 78 * sizeof(void*),
41 "NnApiSLDriverImplFL5 size changed");
42
43 static_assert(ANNSHIM_NO_ERROR == 0, "ANNSHIM_NO_ERROR has changed");
44 static_assert(ANNSHIM_FAILED_TO_LOAD_SL == 1, "ANNSHIM_FAILED_TO_LOAD_SL has changed");
45 static_assert(ANNSHIM_FAILED_TO_REGISTER_SERVICE == 2,
46 "ANNSHIM_FAILED_TO_REGISTER_SERVICE has changed");
47 static_assert(ANNSHIM_GENERAL_ERROR == 3, "ANNSHIM_GENERAL_ERROR has changed");
48 static_assert(ANNSHIM_INVALID_ARGUMENT == 4, "ANNSHIM_INVALID_ARGUMENT has changed");
49
50 using android::neuralnetworks::shim::registerDevices;
51 using android::neuralnetworks::shim::RegistrationParams;
52 using android::neuralnetworks::shim::ShimDeviceInfo;
53
ANeuralNetworksShim_registerSupportLibraryService(const ANeuralNetworksShimRegistrationParams * registrationParams)54 int ANeuralNetworksShim_registerSupportLibraryService(
55 const ANeuralNetworksShimRegistrationParams* registrationParams) {
56 if (registrationParams == nullptr) {
57 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr ";
58 return ANNSHIM_INVALID_ARGUMENT;
59 }
60 const auto* params = reinterpret_cast<const RegistrationParams*>(registrationParams);
61
62 NnApiSLDriverImpl* const nnapiImpl = params->nnapiSupportLibraryPackage;
63 const auto& deviceInfos = params->deviceInfos;
64 const uint32_t numberOfListenerThreads = params->numberOfListenerThreads;
65 const bool registerAsLazyService = params->registerAsLazyService;
66 const bool fallbackToMinimumSupportDevice = params->fallbackToMinimumSupportDevice;
67
68 return static_cast<int>(registerDevices(nnapiImpl, deviceInfos, numberOfListenerThreads,
69 registerAsLazyService, fallbackToMinimumSupportDevice));
70 }
71
ANeuralNetworksShimDeviceInfo_create(ANeuralNetworksShimDeviceInfo ** deviceInfo,const char * deviceName,const char * serviceName)72 int ANeuralNetworksShimDeviceInfo_create(ANeuralNetworksShimDeviceInfo** deviceInfo,
73 const char* deviceName, const char* serviceName) {
74 if (deviceInfo != nullptr) {
75 *deviceInfo = nullptr;
76 }
77
78 if (deviceName == nullptr) {
79 LOG(ERROR) << "Invalid arguments, deviceName passed a nullptr";
80 return ANNSHIM_INVALID_ARGUMENT;
81 }
82
83 auto result = new (std::nothrow)
84 ShimDeviceInfo{.deviceName = std::string(deviceName),
85 .serviceName = (serviceName == nullptr || strlen(serviceName) == 0)
86 ? std::string(deviceName)
87 : std::string(serviceName)};
88 if (result == nullptr) {
89 return ANNSHIM_GENERAL_ERROR;
90 }
91 *deviceInfo = reinterpret_cast<ANeuralNetworksShimDeviceInfo*>(result);
92 return ANNSHIM_NO_ERROR;
93 }
94
ANeuralNetworksShimDeviceInfo_free(ANeuralNetworksShimDeviceInfo * deviceInfo)95 void ANeuralNetworksShimDeviceInfo_free(ANeuralNetworksShimDeviceInfo* deviceInfo) {
96 delete reinterpret_cast<ShimDeviceInfo*>(deviceInfo);
97 }
98
ANeuralNetworksShimRegistrationParams_create(NnApiSLDriverImpl * nnapiSupportLibraryPackage,ANeuralNetworksShimRegistrationParams ** outRegistrationParams)99 int ANeuralNetworksShimRegistrationParams_create(
100 NnApiSLDriverImpl* nnapiSupportLibraryPackage,
101 ANeuralNetworksShimRegistrationParams** outRegistrationParams) {
102 if (outRegistrationParams != nullptr) {
103 *outRegistrationParams = nullptr;
104 }
105
106 if (nnapiSupportLibraryPackage == nullptr) {
107 LOG(ERROR) << "Invalid arguments, nnapiSupportLibraryPackage == nullptr ";
108 return ANNSHIM_INVALID_ARGUMENT;
109 }
110 if (outRegistrationParams == nullptr) {
111 LOG(ERROR) << "Invalid arguments, outRegistrationParams == nullptr ";
112 return ANNSHIM_INVALID_ARGUMENT;
113 }
114
115 auto result = new (std::nothrow) RegistrationParams{
116 .nnapiSupportLibraryPackage = nnapiSupportLibraryPackage,
117 .registerAsLazyService = false,
118 .fallbackToMinimumSupportDevice = false,
119 };
120 if (result == nullptr) {
121 return ANNSHIM_GENERAL_ERROR;
122 }
123 *outRegistrationParams = reinterpret_cast<ANeuralNetworksShimRegistrationParams*>(result);
124 return ANNSHIM_NO_ERROR;
125 }
126
ANeuralNetworksShimRegistrationParams_free(ANeuralNetworksShimRegistrationParams * registrationParams)127 void ANeuralNetworksShimRegistrationParams_free(
128 ANeuralNetworksShimRegistrationParams* registrationParams) {
129 delete reinterpret_cast<RegistrationParams*>(registrationParams);
130 }
131
ANeuralNetworksShimRegistrationParams_addDeviceInfo(ANeuralNetworksShimRegistrationParams * registrationParams,const ANeuralNetworksShimDeviceInfo * deviceInfo)132 int ANeuralNetworksShimRegistrationParams_addDeviceInfo(
133 ANeuralNetworksShimRegistrationParams* registrationParams,
134 const ANeuralNetworksShimDeviceInfo* deviceInfo) {
135 if (registrationParams == nullptr) {
136 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
137 return ANNSHIM_INVALID_ARGUMENT;
138 }
139 if (deviceInfo == nullptr) {
140 LOG(ERROR) << "Invalid arguments, deviceInfo == nullptr";
141 return ANNSHIM_INVALID_ARGUMENT;
142 }
143
144 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
145 auto info = reinterpret_cast<const ShimDeviceInfo*>(deviceInfo);
146 params->deviceInfos.push_back(*info);
147 return ANNSHIM_NO_ERROR;
148 }
149
ANeuralNetworksShimRegistrationParams_setNumberOfListenerThreads(ANeuralNetworksShimRegistrationParams * registrationParams,uint32_t numberOfListenerThreads)150 int ANeuralNetworksShimRegistrationParams_setNumberOfListenerThreads(
151 ANeuralNetworksShimRegistrationParams* registrationParams,
152 uint32_t numberOfListenerThreads) {
153 if (registrationParams == nullptr) {
154 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
155 return ANNSHIM_INVALID_ARGUMENT;
156 }
157 if (registrationParams == 0) {
158 LOG(ERROR) << "Invalid arguments, numberOfListenerThreads == 0";
159 return ANNSHIM_INVALID_ARGUMENT;
160 }
161 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
162 params->numberOfListenerThreads = numberOfListenerThreads;
163 return ANNSHIM_NO_ERROR;
164 }
165
ANeuralNetworksShimRegistrationParams_registerAsLazyService(ANeuralNetworksShimRegistrationParams * registrationParams,bool asLazy)166 int ANeuralNetworksShimRegistrationParams_registerAsLazyService(
167 ANeuralNetworksShimRegistrationParams* registrationParams, bool asLazy) {
168 if (registrationParams == nullptr) {
169 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
170 return ANNSHIM_INVALID_ARGUMENT;
171 }
172 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
173 params->registerAsLazyService = asLazy;
174 return ANNSHIM_NO_ERROR;
175 }
176
ANeuralNetworksShimRegistrationParams_fallbackToMinimumSupportDevice(ANeuralNetworksShimRegistrationParams * registrationParams,bool fallback)177 int ANeuralNetworksShimRegistrationParams_fallbackToMinimumSupportDevice(
178 ANeuralNetworksShimRegistrationParams* registrationParams, bool fallback) {
179 if (registrationParams == nullptr) {
180 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
181 return ANNSHIM_INVALID_ARGUMENT;
182 }
183 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
184 params->fallbackToMinimumSupportDevice = fallback;
185 return ANNSHIM_NO_ERROR;
186 }
187