176cd09d0b73928883aed607dd1348a2359bab241Michael Butler/*
276cd09d0b73928883aed607dd1348a2359bab241Michael Butler * Copyright (C) 2017 The Android Open Source Project
376cd09d0b73928883aed607dd1348a2359bab241Michael Butler *
476cd09d0b73928883aed607dd1348a2359bab241Michael Butler * Licensed under the Apache License, Version 2.0 (the "License");
576cd09d0b73928883aed607dd1348a2359bab241Michael Butler * you may not use this file except in compliance with the License.
676cd09d0b73928883aed607dd1348a2359bab241Michael Butler * You may obtain a copy of the License at
776cd09d0b73928883aed607dd1348a2359bab241Michael Butler *
876cd09d0b73928883aed607dd1348a2359bab241Michael Butler *      http://www.apache.org/licenses/LICENSE-2.0
976cd09d0b73928883aed607dd1348a2359bab241Michael Butler *
1076cd09d0b73928883aed607dd1348a2359bab241Michael Butler * Unless required by applicable law or agreed to in writing, software
1176cd09d0b73928883aed607dd1348a2359bab241Michael Butler * distributed under the License is distributed on an "AS IS" BASIS,
1276cd09d0b73928883aed607dd1348a2359bab241Michael Butler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1376cd09d0b73928883aed607dd1348a2359bab241Michael Butler * See the License for the specific language governing permissions and
1476cd09d0b73928883aed607dd1348a2359bab241Michael Butler * limitations under the License.
1576cd09d0b73928883aed607dd1348a2359bab241Michael Butler */
1676cd09d0b73928883aed607dd1348a2359bab241Michael Butler
1776cd09d0b73928883aed607dd1348a2359bab241Michael Butler#define LOG_TAG "android.hardware.neuralnetworks@1.0-impl-hvx"
1876cd09d0b73928883aed607dd1348a2359bab241Michael Butler
1976cd09d0b73928883aed607dd1348a2359bab241Michael Butler#include "Device.h"
20a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler#include <android-base/logging.h>
21a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler#include <memory>
22a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler#include <mutex>
23a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler#include <thread>
2476cd09d0b73928883aed607dd1348a2359bab241Michael Butler#include "HexagonModel.h"
2576cd09d0b73928883aed607dd1348a2359bab241Michael Butler#include "HexagonUtils.h"
2676cd09d0b73928883aed607dd1348a2359bab241Michael Butler#include "PreparedModel.h"
27cf8d45413b991a3af4a000c8742633a0e0fde54cJean-Luc Brouillet#include "ValidateHal.h"
2876cd09d0b73928883aed607dd1348a2359bab241Michael Butler
2976cd09d0b73928883aed607dd1348a2359bab241Michael Butlernamespace android {
3076cd09d0b73928883aed607dd1348a2359bab241Michael Butlernamespace hardware {
3176cd09d0b73928883aed607dd1348a2359bab241Michael Butlernamespace neuralnetworks {
3276cd09d0b73928883aed607dd1348a2359bab241Michael Butlernamespace V1_0 {
3376cd09d0b73928883aed607dd1348a2359bab241Michael Butlernamespace implementation {
3476cd09d0b73928883aed607dd1348a2359bab241Michael Butler
3576cd09d0b73928883aed607dd1348a2359bab241Michael ButlerDevice::Device() : mCurrentStatus(DeviceStatus::AVAILABLE) {}
3676cd09d0b73928883aed607dd1348a2359bab241Michael Butler
3776cd09d0b73928883aed607dd1348a2359bab241Michael ButlerDevice::~Device() {}
3876cd09d0b73928883aed607dd1348a2359bab241Michael Butler
3982d31136fb09dcd04542655553a9c0455b8f183dMichael Butlerstatic std::once_flag configure_nnlib;
4082d31136fb09dcd04542655553a9c0455b8f183dMichael Butlerstatic void configureHexagon() {
41a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler    std::call_once(configure_nnlib, []() {
42a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        hexagon::Controller::getInstance().config();
43a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler    });
4482d31136fb09dcd04542655553a9c0455b8f183dMichael Butler}
4576cd09d0b73928883aed607dd1348a2359bab241Michael Butler
4676cd09d0b73928883aed607dd1348a2359bab241Michael ButlerReturn<void> Device::getCapabilities(getCapabilities_cb _hidl_cb) {
4782d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    configureHexagon();
4876cd09d0b73928883aed607dd1348a2359bab241Michael Butler
495fa00618520f8d7e394f9d5b2866b6cded835308Jean-Luc Brouillet    // These numbers are approximations for this release.
505fa00618520f8d7e394f9d5b2866b6cded835308Jean-Luc Brouillet    // TODO Change with the actual number.
5176cd09d0b73928883aed607dd1348a2359bab241Michael Butler    PerformanceInfo float32Performance = {
52a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        .execTime = 30.0f, .powerUsage = 2.0f,
5376cd09d0b73928883aed607dd1348a2359bab241Michael Butler    };
5476cd09d0b73928883aed607dd1348a2359bab241Michael Butler
5576cd09d0b73928883aed607dd1348a2359bab241Michael Butler    PerformanceInfo quantized8Performance = {
56a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        .execTime = 0.7f, .powerUsage = 0.7f,
5776cd09d0b73928883aed607dd1348a2359bab241Michael Butler    };
5876cd09d0b73928883aed607dd1348a2359bab241Michael Butler
5976cd09d0b73928883aed607dd1348a2359bab241Michael Butler    Capabilities capabilities = {
60a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        .float32Performance = float32Performance, .quantized8Performance = quantized8Performance,
6176cd09d0b73928883aed607dd1348a2359bab241Michael Butler    };
6276cd09d0b73928883aed607dd1348a2359bab241Michael Butler
6382d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    ErrorStatus status =
64a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        hexagon::isHexagonAvailable() ? ErrorStatus::NONE : ErrorStatus::DEVICE_UNAVAILABLE;
6582d31136fb09dcd04542655553a9c0455b8f183dMichael Butler
6682d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    _hidl_cb(status, capabilities);
6776cd09d0b73928883aed607dd1348a2359bab241Michael Butler    return Void();
6876cd09d0b73928883aed607dd1348a2359bab241Michael Butler}
6976cd09d0b73928883aed607dd1348a2359bab241Michael Butler
7076cd09d0b73928883aed607dd1348a2359bab241Michael ButlerReturn<void> Device::getSupportedOperations(const Model& model,
7176cd09d0b73928883aed607dd1348a2359bab241Michael Butler                                            getSupportedOperations_cb _hidl_cb) {
7282d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    configureHexagon();
7376cd09d0b73928883aed607dd1348a2359bab241Michael Butler
7476cd09d0b73928883aed607dd1348a2359bab241Michael Butler    if (!nn::validateModel(model)) {
7582d31136fb09dcd04542655553a9c0455b8f183dMichael Butler        _hidl_cb(ErrorStatus::INVALID_ARGUMENT, std::vector<bool>{});
7682d31136fb09dcd04542655553a9c0455b8f183dMichael Butler        return Void();
7782d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    }
7882d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    if (!hexagon::isHexagonAvailable()) {
7982d31136fb09dcd04542655553a9c0455b8f183dMichael Butler        _hidl_cb(ErrorStatus::DEVICE_UNAVAILABLE, std::vector<bool>{});
8076cd09d0b73928883aed607dd1348a2359bab241Michael Butler        return Void();
8176cd09d0b73928883aed607dd1348a2359bab241Michael Butler    }
8276cd09d0b73928883aed607dd1348a2359bab241Michael Butler
8376cd09d0b73928883aed607dd1348a2359bab241Michael Butler    hexagon::Model hexagonModel(model);
8476cd09d0b73928883aed607dd1348a2359bab241Michael Butler    std::vector<bool> supported = hexagonModel.supportedOperations();
8576cd09d0b73928883aed607dd1348a2359bab241Michael Butler
8676cd09d0b73928883aed607dd1348a2359bab241Michael Butler    _hidl_cb(ErrorStatus::NONE, supported);
8776cd09d0b73928883aed607dd1348a2359bab241Michael Butler    return Void();
8876cd09d0b73928883aed607dd1348a2359bab241Michael Butler}
8976cd09d0b73928883aed607dd1348a2359bab241Michael Butler
9025d8e8714c120716b2982790818dad502693e2f4Michael Butlerstatic void asyncPrepare(const Model& model, const sp<IPreparedModelCallback>& callback) {
9120a5bcaf2e2776f4f4050a0de00ba9710a242019Michael Butler    std::shared_ptr<hexagon::Model> hexagonModel = std::make_shared<hexagon::Model>(model);
9282d31136fb09dcd04542655553a9c0455b8f183dMichael Butler
939001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler    Return<void> ret;
940f4cdac298cbf691540154154c223db02425b3d0Michael Butler    if (hexagonModel->prepare()) {
959001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler        ret = callback->notify(ErrorStatus::NONE, new PreparedModel(model, hexagonModel));
96a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler    } else {
979001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler        ret = callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
989001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler    }
999001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler    if (!ret.isOk()) {
1009001cd5bf64977f6f61112a37052a03c87ee9550Michael Butler        LOG(ERROR) << "Error in callback's return type: " << ret.description();
10182d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    }
10282d31136fb09dcd04542655553a9c0455b8f183dMichael Butler}
10382d31136fb09dcd04542655553a9c0455b8f183dMichael Butler
10476cd09d0b73928883aed607dd1348a2359bab241Michael ButlerReturn<ErrorStatus> Device::prepareModel(const Model& model,
10576cd09d0b73928883aed607dd1348a2359bab241Michael Butler                                         const sp<IPreparedModelCallback>& callback) {
10682d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    configureHexagon();
10782d31136fb09dcd04542655553a9c0455b8f183dMichael Butler
10876cd09d0b73928883aed607dd1348a2359bab241Michael Butler    if (callback.get() == nullptr) {
10976cd09d0b73928883aed607dd1348a2359bab241Michael Butler        LOG(ERROR) << "invalid callback passed to prepareModel";
11076cd09d0b73928883aed607dd1348a2359bab241Michael Butler        return ErrorStatus::INVALID_ARGUMENT;
11176cd09d0b73928883aed607dd1348a2359bab241Michael Butler    }
11276cd09d0b73928883aed607dd1348a2359bab241Michael Butler    if (!nn::validateModel(model)) {
11376cd09d0b73928883aed607dd1348a2359bab241Michael Butler        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
11476cd09d0b73928883aed607dd1348a2359bab241Michael Butler        return ErrorStatus::INVALID_ARGUMENT;
11576cd09d0b73928883aed607dd1348a2359bab241Michael Butler    }
11682d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    if (!hexagon::isHexagonAvailable()) {
11782d31136fb09dcd04542655553a9c0455b8f183dMichael Butler        callback->notify(ErrorStatus::DEVICE_UNAVAILABLE, nullptr);
11882d31136fb09dcd04542655553a9c0455b8f183dMichael Butler        return ErrorStatus::DEVICE_UNAVAILABLE;
11982d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    }
12076cd09d0b73928883aed607dd1348a2359bab241Michael Butler
1210f4cdac298cbf691540154154c223db02425b3d0Michael Butler    // TODO: once nnlib hanging issue is resolved, make this function
1220f4cdac298cbf691540154154c223db02425b3d0Michael Butler    // asynchronous again
1230f4cdac298cbf691540154154c223db02425b3d0Michael Butler    asyncPrepare(model, callback);
12476cd09d0b73928883aed607dd1348a2359bab241Michael Butler
12576cd09d0b73928883aed607dd1348a2359bab241Michael Butler    return ErrorStatus::NONE;
12676cd09d0b73928883aed607dd1348a2359bab241Michael Butler}
12776cd09d0b73928883aed607dd1348a2359bab241Michael Butler
12876cd09d0b73928883aed607dd1348a2359bab241Michael ButlerReturn<DeviceStatus> Device::getStatus() {
12982d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    configureHexagon();
13082d31136fb09dcd04542655553a9c0455b8f183dMichael Butler    mCurrentStatus =
131a6e68df59d64fceb115b91c69d472f0eebbe6400Michael Butler        hexagon::isHexagonAvailable() ? DeviceStatus::AVAILABLE : DeviceStatus::OFFLINE;
13276cd09d0b73928883aed607dd1348a2359bab241Michael Butler    return mCurrentStatus;
13376cd09d0b73928883aed607dd1348a2359bab241Michael Butler}
13476cd09d0b73928883aed607dd1348a2359bab241Michael Butler
13576cd09d0b73928883aed607dd1348a2359bab241Michael Butler}  // namespace implementation
13676cd09d0b73928883aed607dd1348a2359bab241Michael Butler}  // namespace V1_0
13776cd09d0b73928883aed607dd1348a2359bab241Michael Butler}  // namespace neuralnetworks
13876cd09d0b73928883aed607dd1348a2359bab241Michael Butler}  // namespace hardware
13976cd09d0b73928883aed607dd1348a2359bab241Michael Butler}  // namespace android
140