blob: f12669a6dcccbf4ae86b7f5fe404a48a01f30c93 [file] [log] [blame]
Michael Butler4b276a72020-08-06 23:22:35 -07001/*
2 * Copyright (C) 2020 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#include "Device.h"
18
19#include "Callbacks.h"
20#include "Conversions.h"
21#include "Utils.h"
22
23#include <android/hardware/neuralnetworks/1.0/types.h>
24#include <android/hardware/neuralnetworks/1.1/types.h>
25#include <android/hardware/neuralnetworks/1.2/IDevice.h>
26#include <android/hardware/neuralnetworks/1.2/types.h>
27#include <nnapi/IBuffer.h>
28#include <nnapi/IDevice.h>
29#include <nnapi/IPreparedModel.h>
30#include <nnapi/OperandTypes.h>
31#include <nnapi/Result.h>
32#include <nnapi/Types.h>
Michael Butler49d95e02021-10-15 18:52:52 -070033#include <nnapi/hal/1.0/HandleError.h>
Michael Butlere8645c32021-10-15 18:42:32 -070034#include <nnapi/hal/1.0/ProtectCallback.h>
Michael Butler4b276a72020-08-06 23:22:35 -070035#include <nnapi/hal/1.1/Conversions.h>
36#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070037
38#include <functional>
39#include <memory>
40#include <optional>
41#include <string>
42#include <vector>
43
Michael Butleraad934b2020-12-13 23:06:06 -080044// See hardware/interfaces/neuralnetworks/utils/README.md for more information on HIDL interface
45// lifetimes across processes and for protecting asynchronous calls across HIDL.
46
Michael Butler4b276a72020-08-06 23:22:35 -070047namespace android::hardware::neuralnetworks::V1_2::utils {
Slava Shklyaev77e06d82020-11-30 15:33:17 +000048namespace {
49
Michael Butler7fd03c22020-12-06 21:50:59 -080050nn::GeneralResult<nn::Capabilities> capabilitiesCallback(V1_0::ErrorStatus status,
51 const Capabilities& capabilities) {
Michael Butler49d95e02021-10-15 18:52:52 -070052 HANDLE_STATUS_HIDL(status) << "getting capabilities failed with " << toString(status);
Michael Butler7fd03c22020-12-06 21:50:59 -080053 return nn::convert(capabilities);
54}
55
56nn::GeneralResult<std::string> versionStringCallback(V1_0::ErrorStatus status,
57 const hidl_string& versionString) {
Michael Butler49d95e02021-10-15 18:52:52 -070058 HANDLE_STATUS_HIDL(status) << "getVersionString failed with " << toString(status);
Michael Butler7fd03c22020-12-06 21:50:59 -080059 return versionString;
60}
61
62nn::GeneralResult<nn::DeviceType> deviceTypeCallback(V1_0::ErrorStatus status,
63 DeviceType deviceType) {
Michael Butler49d95e02021-10-15 18:52:52 -070064 HANDLE_STATUS_HIDL(status) << "getDeviceType failed with " << toString(status);
Michael Butler7fd03c22020-12-06 21:50:59 -080065 return nn::convert(deviceType);
66}
67
68nn::GeneralResult<std::vector<nn::Extension>> supportedExtensionsCallback(
69 V1_0::ErrorStatus status, const hidl_vec<Extension>& extensions) {
Michael Butler49d95e02021-10-15 18:52:52 -070070 HANDLE_STATUS_HIDL(status) << "getExtensions failed with " << toString(status);
Michael Butler7fd03c22020-12-06 21:50:59 -080071 return nn::convert(extensions);
72}
73
74nn::GeneralResult<std::pair<uint32_t, uint32_t>> numberOfCacheFilesNeededCallback(
75 V1_0::ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
Michael Butler49d95e02021-10-15 18:52:52 -070076 HANDLE_STATUS_HIDL(status) << "getNumberOfCacheFilesNeeded failed with " << toString(status);
Michael Butler7fd03c22020-12-06 21:50:59 -080077 if (numModelCache > nn::kMaxNumberOfCacheFiles) {
78 return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numModelCache files greater "
79 "than allowed max ("
80 << numModelCache << " vs " << nn::kMaxNumberOfCacheFiles << ")";
81 }
82 if (numDataCache > nn::kMaxNumberOfCacheFiles) {
83 return NN_ERROR() << "getNumberOfCacheFilesNeeded returned numDataCache files greater "
84 "than allowed max ("
85 << numDataCache << " vs " << nn::kMaxNumberOfCacheFiles << ")";
86 }
87 return std::make_pair(numModelCache, numDataCache);
88}
89
90nn::GeneralResult<nn::Capabilities> getCapabilitiesFrom(V1_2::IDevice* device) {
Slava Shklyaev77e06d82020-11-30 15:33:17 +000091 CHECK(device != nullptr);
92
Michael Butler7fd03c22020-12-06 21:50:59 -080093 auto cb = hal::utils::CallbackValue(capabilitiesCallback);
Slava Shklyaev77e06d82020-11-30 15:33:17 +000094
95 const auto ret = device->getCapabilities_1_2(cb);
Michael Butlercca3e202020-11-22 20:25:34 -080096 HANDLE_TRANSPORT_FAILURE(ret);
Slava Shklyaev77e06d82020-11-30 15:33:17 +000097
Michael Butler7fd03c22020-12-06 21:50:59 -080098 return cb.take();
Slava Shklyaev77e06d82020-11-30 15:33:17 +000099}
100
101} // namespace
Michael Butler4b276a72020-08-06 23:22:35 -0700102
Michael Butler7fd03c22020-12-06 21:50:59 -0800103nn::GeneralResult<std::string> getVersionStringFrom(V1_2::IDevice* device) {
Michael Butler4b276a72020-08-06 23:22:35 -0700104 CHECK(device != nullptr);
105
Michael Butler7fd03c22020-12-06 21:50:59 -0800106 auto cb = hal::utils::CallbackValue(versionStringCallback);
Michael Butler4b276a72020-08-06 23:22:35 -0700107
108 const auto ret = device->getVersionString(cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800109 HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler4b276a72020-08-06 23:22:35 -0700110
Michael Butler7fd03c22020-12-06 21:50:59 -0800111 return cb.take();
Michael Butler4b276a72020-08-06 23:22:35 -0700112}
113
Michael Butler7fd03c22020-12-06 21:50:59 -0800114nn::GeneralResult<nn::DeviceType> getDeviceTypeFrom(V1_2::IDevice* device) {
Michael Butler4b276a72020-08-06 23:22:35 -0700115 CHECK(device != nullptr);
116
Michael Butler7fd03c22020-12-06 21:50:59 -0800117 auto cb = hal::utils::CallbackValue(deviceTypeCallback);
Michael Butler4b276a72020-08-06 23:22:35 -0700118
119 const auto ret = device->getType(cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800120 HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler4b276a72020-08-06 23:22:35 -0700121
Michael Butler7fd03c22020-12-06 21:50:59 -0800122 return cb.take();
Michael Butler4b276a72020-08-06 23:22:35 -0700123}
124
Michael Butler7fd03c22020-12-06 21:50:59 -0800125nn::GeneralResult<std::vector<nn::Extension>> getSupportedExtensionsFrom(V1_2::IDevice* device) {
Michael Butler4b276a72020-08-06 23:22:35 -0700126 CHECK(device != nullptr);
127
Michael Butler7fd03c22020-12-06 21:50:59 -0800128 auto cb = hal::utils::CallbackValue(supportedExtensionsCallback);
Michael Butler4b276a72020-08-06 23:22:35 -0700129
130 const auto ret = device->getSupportedExtensions(cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800131 HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler4b276a72020-08-06 23:22:35 -0700132
Michael Butler7fd03c22020-12-06 21:50:59 -0800133 return cb.take();
Michael Butler4b276a72020-08-06 23:22:35 -0700134}
135
Michael Butler7fd03c22020-12-06 21:50:59 -0800136nn::GeneralResult<std::pair<uint32_t, uint32_t>> getNumberOfCacheFilesNeededFrom(
Michael Butler4b276a72020-08-06 23:22:35 -0700137 V1_2::IDevice* device) {
138 CHECK(device != nullptr);
139
Michael Butler7fd03c22020-12-06 21:50:59 -0800140 auto cb = hal::utils::CallbackValue(numberOfCacheFilesNeededCallback);
Michael Butler4b276a72020-08-06 23:22:35 -0700141
142 const auto ret = device->getNumberOfCacheFilesNeeded(cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800143 HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler4b276a72020-08-06 23:22:35 -0700144
Michael Butler7fd03c22020-12-06 21:50:59 -0800145 return cb.take();
Michael Butler4b276a72020-08-06 23:22:35 -0700146}
147
148nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
149 sp<V1_2::IDevice> device) {
150 if (name.empty()) {
151 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
152 << "V1_2::utils::Device::create must have non-empty name";
153 }
154 if (device == nullptr) {
155 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
156 << "V1_2::utils::Device::create must have non-null device";
157 }
158
Michael Butler7fd03c22020-12-06 21:50:59 -0800159 auto versionString = NN_TRY(getVersionStringFrom(device.get()));
160 const auto deviceType = NN_TRY(getDeviceTypeFrom(device.get()));
161 auto extensions = NN_TRY(getSupportedExtensionsFrom(device.get()));
162 auto capabilities = NN_TRY(getCapabilitiesFrom(device.get()));
163 const auto numberOfCacheFilesNeeded = NN_TRY(getNumberOfCacheFilesNeededFrom(device.get()));
Michael Butler4b276a72020-08-06 23:22:35 -0700164
165 auto deathHandler = NN_TRY(hal::utils::DeathHandler::create(device));
166 return std::make_shared<const Device>(
167 PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
168 std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
169 std::move(device), std::move(deathHandler));
170}
171
172Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
173 nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
174 nn::Capabilities capabilities,
175 std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded, sp<V1_2::IDevice> device,
176 hal::utils::DeathHandler deathHandler)
177 : kName(std::move(name)),
178 kVersionString(std::move(versionString)),
179 kDeviceType(deviceType),
180 kExtensions(std::move(extensions)),
181 kCapabilities(std::move(capabilities)),
182 kNumberOfCacheFilesNeeded(numberOfCacheFilesNeeded),
183 kDevice(std::move(device)),
184 kDeathHandler(std::move(deathHandler)) {}
185
186const std::string& Device::getName() const {
187 return kName;
188}
189
190const std::string& Device::getVersionString() const {
191 return kVersionString;
192}
193
194nn::Version Device::getFeatureLevel() const {
195 return nn::Version::ANDROID_Q;
196}
197
198nn::DeviceType Device::getType() const {
199 return kDeviceType;
200}
201
202const std::vector<nn::Extension>& Device::getSupportedExtensions() const {
203 return kExtensions;
204}
205
206const nn::Capabilities& Device::getCapabilities() const {
207 return kCapabilities;
208}
209
210std::pair<uint32_t, uint32_t> Device::getNumberOfCacheFilesNeeded() const {
211 return kNumberOfCacheFilesNeeded;
212}
213
214nn::GeneralResult<void> Device::wait() const {
215 const auto ret = kDevice->ping();
Michael Butlercca3e202020-11-22 20:25:34 -0800216 HANDLE_TRANSPORT_FAILURE(ret);
217 return {};
Michael Butler4b276a72020-08-06 23:22:35 -0700218}
219
220nn::GeneralResult<std::vector<bool>> Device::getSupportedOperations(const nn::Model& model) const {
221 // Ensure that model is ready for IPC.
222 std::optional<nn::Model> maybeModelInShared;
223 const nn::Model& modelInShared =
224 NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
225
226 const auto hidlModel = NN_TRY(convert(modelInShared));
227
Michael Butler7fd03c22020-12-06 21:50:59 -0800228 auto cb = hal::utils::CallbackValue(V1_0::utils::supportedOperationsCallback);
Michael Butler4b276a72020-08-06 23:22:35 -0700229
230 const auto ret = kDevice->getSupportedOperations_1_2(hidlModel, cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800231 HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler4b276a72020-08-06 23:22:35 -0700232
Michael Butler7fd03c22020-12-06 21:50:59 -0800233 return cb.take();
Michael Butler4b276a72020-08-06 23:22:35 -0700234}
235
236nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModel(
237 const nn::Model& model, nn::ExecutionPreference preference, nn::Priority /*priority*/,
Slava Shklyaev49817a02020-10-27 18:44:01 +0000238 nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache,
239 const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
Michael Butler4b276a72020-08-06 23:22:35 -0700240 // Ensure that model is ready for IPC.
241 std::optional<nn::Model> maybeModelInShared;
242 const nn::Model& modelInShared =
243 NN_TRY(hal::utils::flushDataFromPointerToShared(&model, &maybeModelInShared));
244
245 const auto hidlModel = NN_TRY(convert(modelInShared));
Michael Butler7fd03c22020-12-06 21:50:59 -0800246 const auto hidlPreference = NN_TRY(convert(preference));
Michael Butler4b276a72020-08-06 23:22:35 -0700247 const auto hidlModelCache = NN_TRY(convert(modelCache));
248 const auto hidlDataCache = NN_TRY(convert(dataCache));
Michael Butler7fd03c22020-12-06 21:50:59 -0800249 const auto hidlToken = CacheToken{token};
Michael Butler4b276a72020-08-06 23:22:35 -0700250
251 const auto cb = sp<PreparedModelCallback>::make();
252 const auto scoped = kDeathHandler.protectCallback(cb.get());
253
254 const auto ret = kDevice->prepareModel_1_2(hidlModel, hidlPreference, hidlModelCache,
255 hidlDataCache, hidlToken, cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800256 const auto status = HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler49d95e02021-10-15 18:52:52 -0700257 HANDLE_STATUS_HIDL(status) << "model preparation failed with " << toString(status);
Michael Butler4b276a72020-08-06 23:22:35 -0700258
259 return cb->get();
260}
261
262nn::GeneralResult<nn::SharedPreparedModel> Device::prepareModelFromCache(
Slava Shklyaev49817a02020-10-27 18:44:01 +0000263 nn::OptionalTimePoint /*deadline*/, const std::vector<nn::SharedHandle>& modelCache,
264 const std::vector<nn::SharedHandle>& dataCache, const nn::CacheToken& token) const {
Michael Butler4b276a72020-08-06 23:22:35 -0700265 const auto hidlModelCache = NN_TRY(convert(modelCache));
266 const auto hidlDataCache = NN_TRY(convert(dataCache));
Michael Butler7fd03c22020-12-06 21:50:59 -0800267 const auto hidlToken = CacheToken{token};
Michael Butler4b276a72020-08-06 23:22:35 -0700268
269 const auto cb = sp<PreparedModelCallback>::make();
270 const auto scoped = kDeathHandler.protectCallback(cb.get());
271
272 const auto ret = kDevice->prepareModelFromCache(hidlModelCache, hidlDataCache, hidlToken, cb);
Michael Butlercca3e202020-11-22 20:25:34 -0800273 const auto status = HANDLE_TRANSPORT_FAILURE(ret);
Michael Butler49d95e02021-10-15 18:52:52 -0700274 HANDLE_STATUS_HIDL(status) << "model preparation from cache failed with " << toString(status);
Michael Butler4b276a72020-08-06 23:22:35 -0700275
276 return cb->get();
277}
278
279nn::GeneralResult<nn::SharedBuffer> Device::allocate(
280 const nn::BufferDesc& /*desc*/,
281 const std::vector<nn::SharedPreparedModel>& /*preparedModels*/,
282 const std::vector<nn::BufferRole>& /*inputRoles*/,
283 const std::vector<nn::BufferRole>& /*outputRoles*/) const {
284 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
285 << "IDevice::allocate not supported on 1.2 HAL service";
286}
287
288} // namespace android::hardware::neuralnetworks::V1_2::utils