Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2017 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 "Manager"
     18 
     19 #include "Manager.h"
     20 #include "HalInterfaces.h"
     21 #include "Utils.h"
     22 
     23 #include <android/hidl/manager/1.0/IServiceManager.h>
     24 #include <hidl/HidlTransportSupport.h>
     25 #include <hidl/ServiceManagement.h>
     26 
     27 #include <algorithm>
     28 #include <functional>
     29 
     30 namespace android {
     31 namespace nn {
     32 
     33 Device::Device(std::string name, const sp<V1_0::IDevice>& device) :
     34       mName(std::move(name)), mInterface(device) {}
     35 
     36 // TODO: handle errors from initialize correctly
     37 bool Device::initialize() {
     38 #ifdef NN_DEBUGGABLE
     39     static const char samplePrefix[] = "sample";
     40 
     41     mSupported =
     42             (mName.substr(0, sizeof(samplePrefix) - 1)  == samplePrefix)
     43             ? getProp("debug.nn.sample.supported") : 0;
     44 #endif  // NN_DEBUGGABLE
     45 
     46     ErrorStatus status = ErrorStatus::GENERAL_FAILURE;
     47     Capabilities capabilities;
     48     std::tie(status, capabilities) = mInterface.getCapabilities();
     49 
     50     if (status != ErrorStatus::NONE) {
     51         LOG(ERROR) << "IDevice::getCapabilities returned the error " << toString(status);
     52     } else {
     53         VLOG(MANAGER) << "Capab " << capabilities.float32Performance.execTime;
     54         VLOG(MANAGER) << "Capab " << capabilities.quantized8Performance.execTime;
     55         VLOG(MANAGER) << "Capab " << capabilities.relaxedFloat32toFloat16Performance.execTime;
     56         mFloat32Performance = capabilities.float32Performance;
     57         mQuantized8Performance = capabilities.quantized8Performance;
     58         mRelaxedFloat32toFloat16Performance = capabilities.relaxedFloat32toFloat16Performance;
     59     }
     60 
     61     return status == ErrorStatus::NONE;
     62 }
     63 
     64 void Device::getSupportedOperations(const Model& hidlModel,
     65                                     hidl_vec<bool>* outSupportedOperations) {
     66     // Query the driver for what it can do.
     67     ErrorStatus status = ErrorStatus::GENERAL_FAILURE;
     68     hidl_vec<bool> supportedOperations;
     69     std::tie(status, supportedOperations) = mInterface.getSupportedOperations(hidlModel);
     70 
     71     if (status != ErrorStatus::NONE) {
     72         LOG(ERROR) << "IDevice::getSupportedOperations returned the error " << toString(status);
     73         // Set the supported operation vectors to all false, so we won't use this driver.
     74         outSupportedOperations->resize(hidlModel.operations.size());
     75         std::fill(outSupportedOperations->begin(), outSupportedOperations->end(), false);
     76         return;
     77     }
     78     if (supportedOperations.size() != hidlModel.operations.size()) {
     79         LOG(ERROR) << "IDevice::getSupportedOperations returned a vector of length "
     80                    << supportedOperations.size() << " when expecting "
     81                    << hidlModel.operations.size();
     82         // Set the supported operation vectors to all false, so we won't use this driver.
     83         outSupportedOperations->resize(hidlModel.operations.size());
     84         std::fill(outSupportedOperations->begin(), outSupportedOperations->end(), false);
     85         return;
     86     }
     87 
     88     *outSupportedOperations = supportedOperations;
     89 
     90 #ifdef NN_DEBUGGABLE
     91     if (mSupported != 1) {
     92         return;
     93     }
     94 
     95     const uint32_t baseAccumulator = std::hash<std::string>{}(mName);
     96     for (size_t operationIndex = 0; operationIndex < outSupportedOperations->size();
     97          operationIndex++) {
     98         if (!(*outSupportedOperations)[operationIndex]) {
     99             continue;
    100         }
    101 
    102         uint32_t accumulator = baseAccumulator;
    103         const Operation &operation = hidlModel.operations[operationIndex];
    104         accumulator ^= static_cast<uint32_t>(operation.type);
    105         auto accumulateOperands = [&hidlModel, &accumulator](const hidl_vec<uint32_t>& operands) {
    106             for (uint32_t operandIndex : operands) {
    107                 const Operand& operand = hidlModel.operands[operandIndex];
    108                 accumulator ^= static_cast<uint32_t>(operand.type);
    109                 accumulator ^= operand.dimensions.size();
    110                 for (uint32_t dimension : operand.dimensions) {
    111                     accumulator ^= dimension;
    112                     if (operand.lifetime == OperandLifeTime::CONSTANT_COPY ||
    113                         operand.lifetime == OperandLifeTime::CONSTANT_REFERENCE) {
    114                         accumulator ^= 1;
    115                     }
    116                 }
    117             }
    118         };
    119         accumulateOperands(operation.inputs);
    120         accumulateOperands(operation.outputs);
    121         if (accumulator & 1) {
    122             (*outSupportedOperations)[operationIndex] = false;
    123         }
    124     }
    125 #endif  // NN_DEBUGGABLE
    126 }
    127 
    128 DeviceManager* DeviceManager::get() {
    129     static DeviceManager manager;
    130     return &manager;
    131 }
    132 
    133 void DeviceManager::findAvailableDevices() {
    134     using ::android::hidl::manager::V1_0::IServiceManager;
    135     VLOG(MANAGER) << "findAvailableDevices";
    136 
    137     sp<IServiceManager> manager = hardware::defaultServiceManager();
    138     if (manager == nullptr) {
    139         LOG(ERROR) << "Unable to open defaultServiceManager";
    140         return;
    141     }
    142 
    143     manager->listByInterface(V1_0::IDevice::descriptor, [this](const hidl_vec<hidl_string>& names) {
    144         for (const auto& name : names) {
    145             VLOG(MANAGER) << "Found interface " << name.c_str();
    146             sp<V1_0::IDevice> device = V1_0::IDevice::getService(name);
    147             if (device == nullptr) {
    148                 LOG(ERROR) << "Got a null IDEVICE for " << name.c_str();
    149                 continue;
    150             }
    151             registerDevice(name.c_str(), device);
    152         }
    153     });
    154 }
    155 
    156 void DeviceManager::registerDevice(const char* name, const sp<V1_0::IDevice>& device) {
    157     auto d = std::make_shared<Device>(name, device);
    158     if (d->initialize()) {
    159         mDevices.push_back(d);
    160     }
    161 }
    162 
    163 DeviceManager::DeviceManager() {
    164     VLOG(MANAGER) << "DeviceManager::DeviceManager";
    165     findAvailableDevices();
    166 #ifdef NN_DEBUGGABLE
    167     mPartitioning = getProp("debug.nn.partition", kPartitioningDefault);
    168     mDebugNNCpuOnly = (getProp("debug.nn.cpuonly") != 0);
    169 #endif  // NN_DEBUGGABLE
    170 }
    171 
    172 }  // namespace nn
    173 }  // namespace android
    174