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(NnApiSLDriverImplFL6, base.implFeatureLevel) == 0,
35 ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL6 struct");
36 static_assert(offsetof(NnApiSLDriverImplFL7, base.implFeatureLevel) == 0,
37 ".base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL7 struct");
38 static_assert(offsetof(NnApiSLDriverImplFL8, base) == 0,
39 ".base is not at offset 0 of a NnApiSLDriverImplFL8 struct");
40 static_assert(offsetof(NnApiSLDriverImplFL8, base.base) == 0,
41 ".base.base is not at offset 0 of a NnApiSLDriverImplFL8 struct");
42 static_assert(offsetof(NnApiSLDriverImplFL8, base.base.implFeatureLevel) == 0,
43 ".base.base.implFeatureLevel is not at offset 0 of a NnApiSLDriverImplFL8 struct");
44 static_assert(offsetof(NnApiSLDriverImpl, implFeatureLevel) == 0,
45 ".implFeatureLevel is not at offset 0 of a NnApiSLDriverImpl struct");
46
47 static_assert(sizeof(NnApiSLDriverImpl) == sizeof(int64_t), "NnApiSLDriverImpl size changed");
48
49 // NOTE: NnApiSLDriverImplFL5 is currently aligned to 8 bytes. In prior versions of the Support
50 // Library interface, we added a "reserved_placeholder" to force alignment on 32-bit platforms. This
51 // may need to be done in the future if this struct again becomes unaligned. This would look like:
52 // /**
53 // * Extra pointer required to align to 8 bytes on 32bit archs.
54 // */
55 // void (*reserved_placeholder1)();
56 static_assert(sizeof(NnApiSLDriverImplFL5) == sizeof(int64_t) + 104 * sizeof(void*),
57 "NnApiSLDriverImplFL5 size changed");
58 static_assert(sizeof(NnApiSLDriverImplFL6) == sizeof(int64_t) + 104 * sizeof(void*),
59 "NnApiSLDriverImplFL6 size changed");
60 static_assert(sizeof(NnApiSLDriverImplFL7) == sizeof(int64_t) + 104 * sizeof(void*),
61 "NnApiSLDriverImplFL7 size changed");
62 static_assert(sizeof(NnApiSLDriverImplFL8) == sizeof(NnApiSLDriverImplFL7) + 2 * sizeof(void*),
63 "NnApiSLDriverImplFL8 size changed");
64
65 static_assert(ANNSHIM_NO_ERROR == 0, "ANNSHIM_NO_ERROR has changed");
66 static_assert(ANNSHIM_FAILED_TO_LOAD_SL == 1, "ANNSHIM_FAILED_TO_LOAD_SL has changed");
67 static_assert(ANNSHIM_FAILED_TO_REGISTER_SERVICE == 2,
68 "ANNSHIM_FAILED_TO_REGISTER_SERVICE has changed");
69 static_assert(ANNSHIM_GENERAL_ERROR == 3, "ANNSHIM_GENERAL_ERROR has changed");
70 static_assert(ANNSHIM_INVALID_ARGUMENT == 4, "ANNSHIM_INVALID_ARGUMENT has changed");
71
72 using android::neuralnetworks::shim::registerDevices;
73 using android::neuralnetworks::shim::RegistrationParams;
74 using android::neuralnetworks::shim::ShimDeviceInfo;
75
ANeuralNetworksShim_registerSupportLibraryService(const ANeuralNetworksShimRegistrationParams * registrationParams)76 int ANeuralNetworksShim_registerSupportLibraryService(
77 const ANeuralNetworksShimRegistrationParams* registrationParams) {
78 if (registrationParams == nullptr) {
79 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr ";
80 return ANNSHIM_INVALID_ARGUMENT;
81 }
82 const auto* params = reinterpret_cast<const RegistrationParams*>(registrationParams);
83
84 NnApiSLDriverImpl* const nnapiImpl = params->nnapiSupportLibraryPackage;
85 const auto& deviceInfos = params->deviceInfos;
86 const uint32_t numberOfListenerThreads = params->numberOfListenerThreads;
87 const bool registerAsLazyService = params->registerAsLazyService;
88 const bool fallbackToMinimumSupportDevice = params->fallbackToMinimumSupportDevice;
89
90 return static_cast<int>(registerDevices(nnapiImpl, deviceInfos, numberOfListenerThreads,
91 registerAsLazyService, fallbackToMinimumSupportDevice));
92 }
93
ANeuralNetworksShimDeviceInfo_create(ANeuralNetworksShimDeviceInfo ** deviceInfo,const char * deviceName,const char * serviceName)94 int ANeuralNetworksShimDeviceInfo_create(ANeuralNetworksShimDeviceInfo** deviceInfo,
95 const char* deviceName, const char* serviceName) {
96 if (deviceInfo != nullptr) {
97 *deviceInfo = nullptr;
98 }
99
100 if (deviceName == nullptr) {
101 LOG(ERROR) << "Invalid arguments, deviceName passed a nullptr";
102 return ANNSHIM_INVALID_ARGUMENT;
103 }
104
105 auto result = new (std::nothrow)
106 ShimDeviceInfo{.deviceName = std::string(deviceName),
107 .serviceName = (serviceName == nullptr || strlen(serviceName) == 0)
108 ? std::string(deviceName)
109 : std::string(serviceName)};
110 if (result == nullptr) {
111 return ANNSHIM_GENERAL_ERROR;
112 }
113 *deviceInfo = reinterpret_cast<ANeuralNetworksShimDeviceInfo*>(result);
114 return ANNSHIM_NO_ERROR;
115 }
116
ANeuralNetworksShimDeviceInfo_free(ANeuralNetworksShimDeviceInfo * deviceInfo)117 void ANeuralNetworksShimDeviceInfo_free(ANeuralNetworksShimDeviceInfo* deviceInfo) {
118 delete reinterpret_cast<ShimDeviceInfo*>(deviceInfo);
119 }
120
ANeuralNetworksShimRegistrationParams_create(NnApiSLDriverImpl * nnapiSupportLibraryPackage,ANeuralNetworksShimRegistrationParams ** outRegistrationParams)121 int ANeuralNetworksShimRegistrationParams_create(
122 NnApiSLDriverImpl* nnapiSupportLibraryPackage,
123 ANeuralNetworksShimRegistrationParams** outRegistrationParams) {
124 if (outRegistrationParams != nullptr) {
125 *outRegistrationParams = nullptr;
126 }
127
128 if (nnapiSupportLibraryPackage == nullptr) {
129 LOG(ERROR) << "Invalid arguments, nnapiSupportLibraryPackage == nullptr ";
130 return ANNSHIM_INVALID_ARGUMENT;
131 }
132 if (outRegistrationParams == nullptr) {
133 LOG(ERROR) << "Invalid arguments, outRegistrationParams == nullptr ";
134 return ANNSHIM_INVALID_ARGUMENT;
135 }
136
137 auto result = new (std::nothrow) RegistrationParams{
138 .nnapiSupportLibraryPackage = nnapiSupportLibraryPackage,
139 .registerAsLazyService = false,
140 .fallbackToMinimumSupportDevice = false,
141 };
142 if (result == nullptr) {
143 return ANNSHIM_GENERAL_ERROR;
144 }
145 *outRegistrationParams = reinterpret_cast<ANeuralNetworksShimRegistrationParams*>(result);
146 return ANNSHIM_NO_ERROR;
147 }
148
ANeuralNetworksShimRegistrationParams_free(ANeuralNetworksShimRegistrationParams * registrationParams)149 void ANeuralNetworksShimRegistrationParams_free(
150 ANeuralNetworksShimRegistrationParams* registrationParams) {
151 delete reinterpret_cast<RegistrationParams*>(registrationParams);
152 }
153
ANeuralNetworksShimRegistrationParams_addDeviceInfo(ANeuralNetworksShimRegistrationParams * registrationParams,const ANeuralNetworksShimDeviceInfo * deviceInfo)154 int ANeuralNetworksShimRegistrationParams_addDeviceInfo(
155 ANeuralNetworksShimRegistrationParams* registrationParams,
156 const ANeuralNetworksShimDeviceInfo* deviceInfo) {
157 if (registrationParams == nullptr) {
158 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
159 return ANNSHIM_INVALID_ARGUMENT;
160 }
161 if (deviceInfo == nullptr) {
162 LOG(ERROR) << "Invalid arguments, deviceInfo == nullptr";
163 return ANNSHIM_INVALID_ARGUMENT;
164 }
165
166 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
167 auto info = reinterpret_cast<const ShimDeviceInfo*>(deviceInfo);
168 params->deviceInfos.push_back(*info);
169 return ANNSHIM_NO_ERROR;
170 }
171
ANeuralNetworksShimRegistrationParams_setNumberOfListenerThreads(ANeuralNetworksShimRegistrationParams * registrationParams,uint32_t numberOfListenerThreads)172 int ANeuralNetworksShimRegistrationParams_setNumberOfListenerThreads(
173 ANeuralNetworksShimRegistrationParams* registrationParams,
174 uint32_t numberOfListenerThreads) {
175 if (registrationParams == nullptr) {
176 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
177 return ANNSHIM_INVALID_ARGUMENT;
178 }
179 if (registrationParams == 0) {
180 LOG(ERROR) << "Invalid arguments, numberOfListenerThreads == 0";
181 return ANNSHIM_INVALID_ARGUMENT;
182 }
183 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
184 params->numberOfListenerThreads = numberOfListenerThreads;
185 return ANNSHIM_NO_ERROR;
186 }
187
ANeuralNetworksShimRegistrationParams_registerAsLazyService(ANeuralNetworksShimRegistrationParams * registrationParams,bool asLazy)188 int ANeuralNetworksShimRegistrationParams_registerAsLazyService(
189 ANeuralNetworksShimRegistrationParams* registrationParams, bool asLazy) {
190 if (registrationParams == nullptr) {
191 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
192 return ANNSHIM_INVALID_ARGUMENT;
193 }
194 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
195 params->registerAsLazyService = asLazy;
196 return ANNSHIM_NO_ERROR;
197 }
198
ANeuralNetworksShimRegistrationParams_fallbackToMinimumSupportDevice(ANeuralNetworksShimRegistrationParams * registrationParams,bool fallback)199 int ANeuralNetworksShimRegistrationParams_fallbackToMinimumSupportDevice(
200 ANeuralNetworksShimRegistrationParams* registrationParams, bool fallback) {
201 if (registrationParams == nullptr) {
202 LOG(ERROR) << "Invalid arguments, registrationParams == nullptr";
203 return ANNSHIM_INVALID_ARGUMENT;
204 }
205 auto params = reinterpret_cast<RegistrationParams*>(registrationParams);
206 params->fallbackToMinimumSupportDevice = fallback;
207 return ANNSHIM_NO_ERROR;
208 }
209