blob: 44f8ea9ff843e06441e4de9fbea4f2149d6a9566 [file] [log] [blame]
/*
* 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 "InvalidDevice"
#include "InvalidDevice.h"
#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
#include <android/binder_auto_utils.h>
#include "Conversions.h"
#include "Utils.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace aidl::android::hardware::neuralnetworks {
namespace {
ndk::ScopedAStatus toAStatus(ErrorStatus errorStatus, const std::string& errorMessage) {
if (errorStatus == ErrorStatus::NONE) {
return ndk::ScopedAStatus::ok();
}
return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
static_cast<int32_t>(errorStatus), errorMessage.c_str());
}
} // namespace
std::shared_ptr<InvalidDevice> InvalidDevice::create() {
constexpr auto perf = PerformanceInfo{
.execTime = std::numeric_limits<float>::max(),
.powerUsage = std::numeric_limits<float>::max(),
};
auto capabilities = Capabilities{
.relaxedFloat32toFloat16PerformanceScalar = perf,
.relaxedFloat32toFloat16PerformanceTensor = perf,
.operandPerformance = {},
.ifPerformance = perf,
.whilePerformance = perf,
};
constexpr auto numberOfCacheFiles = NumberOfCacheFiles{
.numModelCache = 0,
.numDataCache = 0,
};
std::vector<Extension> extensions{};
constexpr auto deviceType = DeviceType::OTHER;
std::string versionString = "invalid";
return ndk::SharedRefBase::make<InvalidDevice>(std::move(capabilities), numberOfCacheFiles,
std::move(extensions), deviceType,
std::move(versionString));
}
InvalidDevice::InvalidDevice(Capabilities capabilities,
const NumberOfCacheFiles& numberOfCacheFiles,
std::vector<Extension> extensions, DeviceType deviceType,
std::string versionString)
: kCapabilities(std::move(capabilities)),
kNumberOfCacheFiles(numberOfCacheFiles),
kExtensions(std::move(extensions)),
kDeviceType(deviceType),
kVersionString(std::move(versionString)) {}
ndk::ScopedAStatus InvalidDevice::allocate(
const BufferDesc& /*desc*/, const std::vector<IPreparedModelParcel>& /*preparedModels*/,
const std::vector<BufferRole>& /*inputRoles*/,
const std::vector<BufferRole>& /*outputRoles*/, DeviceBuffer* /*deviceBuffer*/) {
return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
}
ndk::ScopedAStatus InvalidDevice::getCapabilities(Capabilities* capabilities) {
*capabilities = kCapabilities;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::getNumberOfCacheFilesNeeded(
NumberOfCacheFiles* numberOfCacheFiles) {
*numberOfCacheFiles = kNumberOfCacheFiles;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::getSupportedExtensions(std::vector<Extension>* extensions) {
*extensions = kExtensions;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::getSupportedOperations(const Model& model,
std::vector<bool>* supportedOperations) {
if (const auto result = utils::validate(model); !result.ok()) {
return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
}
*supportedOperations = std::vector<bool>(model.main.operations.size(), false);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::getType(DeviceType* deviceType) {
*deviceType = kDeviceType;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::getVersionString(std::string* versionString) {
*versionString = kVersionString;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::prepareModel(
const Model& model, ExecutionPreference preference, Priority priority, int64_t deadline,
const std::vector<ndk::ScopedFileDescriptor>& modelCache,
const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
const std::shared_ptr<IPreparedModelCallback>& callback) {
if (callback.get() == nullptr) {
return toAStatus(ErrorStatus::INVALID_ARGUMENT,
"invalid callback passed to InvalidDevice::prepareModel");
}
if (const auto result = utils::validate(model); !result.ok()) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
}
if (const auto result = utils::validate(preference); !result.ok()) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
}
if (const auto result = utils::validate(priority); !result.ok()) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
}
if (deadline < -1) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT,
"Invalid deadline " + std::to_string(deadline));
}
if (modelCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numModelCache)) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT,
"Invalid modelCache, size = " + std::to_string(modelCache.size()));
}
if (dataCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numDataCache)) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT,
"Invalid modelCache, size = " + std::to_string(dataCache.size()));
}
if (token.size() != IDevice::BYTE_SIZE_OF_CACHE_TOKEN) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(
ErrorStatus::INVALID_ARGUMENT,
"Invalid cache token, size = " + std::to_string(IDevice::BYTE_SIZE_OF_CACHE_TOKEN));
}
callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus InvalidDevice::prepareModelWithConfig(
const Model& model, const PrepareModelConfig& config,
const std::shared_ptr<IPreparedModelCallback>& callback) {
if (!utils::valid(config.extensionNameToPrefix)) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT, "Invalid extensionNameToPrefix");
}
for (const auto& hint : config.compilationHints) {
auto result = std::find_if(config.extensionNameToPrefix.begin(),
config.extensionNameToPrefix.end(),
[&hint](const ExtensionNameAndPrefix& extension) {
uint16_t prefix = static_cast<uint32_t>(hint.token) >>
IDevice::EXTENSION_TYPE_LOW_BITS_TYPE;
return prefix == extension.prefix;
});
if (result == config.extensionNameToPrefix.end()) {
callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
return toAStatus(ErrorStatus::INVALID_ARGUMENT,
"Invalid token for compilation hints: " + std::to_string(hint.token));
}
}
return prepareModel(model, config.preference, config.priority, config.deadlineNs,
config.modelCache, config.dataCache, utils::toVec(config.cacheToken),
callback);
}
ndk::ScopedAStatus InvalidDevice::prepareModelFromCache(
int64_t /*deadline*/, const std::vector<ndk::ScopedFileDescriptor>& /*modelCache*/,
const std::vector<ndk::ScopedFileDescriptor>& /*dataCache*/,
const std::vector<uint8_t>& /*token*/,
const std::shared_ptr<IPreparedModelCallback>& callback) {
callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
}
} // namespace aidl::android::hardware::neuralnetworks