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 // TODO: handle errors from initialize correctly
     34 bool Device::initialize() {
     35 #ifdef NN_DEBUGGABLE
     36     static const char samplePrefix[] = "sample";
     37 
     38     mSupported =
     39             (mName.substr(0, sizeof(samplePrefix) - 1)  == samplePrefix)
     40             ? getProp("debug.nn.sample.supported") : 0;
     41 #endif  // NN_DEBUGGABLE
     42     bool success = false;
     43     auto ret = mInterface->getCapabilities([&](ErrorStatus status,
     44                                                const Capabilities& capabilities) {
     45         if (status != ErrorStatus::NONE) {
     46             LOG(ERROR) << "IDevice::getCapabilities returned the error " << toString(status);
     47         } else {
     48             VLOG(MANAGER) << "Capab " << capabilities.float32Performance.execTime;
     49             VLOG(MANAGER) << "Capab " << capabilities.quantized8Performance.execTime;
     50             mFloat32Performance = capabilities.float32Performance;
     51             mQuantized8Performance = capabilities.quantized8Performance;
     52             success = true;
     53         }
     54     });
     55     if (!ret.isOk()) {
     56         LOG(ERROR) << "IDevice::getCapabilities failed for " << getName()
     57                    << ": " << ret.description();
     58     }
     59     return success;
     60 }
     61 
     62 void Device::getSupportedOperations(const Model& hidlModel,
     63                                     hidl_vec<bool>* outSupportedOperations) const {
     64     auto ret = mInterface->getSupportedOperations(
     65         hidlModel,
     66         [outSupportedOperations](ErrorStatus status, const hidl_vec<bool>& supportedOperations) {
     67             if (status != ErrorStatus::NONE) {
     68                 LOG(ERROR)
     69                         << "IDevice::getSupportedOperations returned the error "
     70                         << toString(status);
     71             }
     72             *outSupportedOperations = supportedOperations;
     73         });
     74 
     75     if (!ret.isOk()) {
     76         LOG(ERROR) << "IDevice::getSupportedOperations failed for " << getName()
     77                    << ": " << ret.description();
     78         outSupportedOperations->resize(hidlModel.operations.size());
     79         std::fill(outSupportedOperations->begin(), outSupportedOperations->end(), false);
     80         return;
     81     }
     82 
     83 #ifdef NN_DEBUGGABLE
     84     if (mSupported != 1) {
     85         return;
     86     }
     87 
     88     const uint32_t baseAccumulator = std::hash<std::string>{}(mName);
     89     for (size_t operationIndex = 0; operationIndex < outSupportedOperations->size();
     90          operationIndex++) {
     91         if (!(*outSupportedOperations)[operationIndex]) {
     92             continue;
     93         }
     94 
     95         uint32_t accumulator = baseAccumulator;
     96         const Operation &operation = hidlModel.operations[operationIndex];
     97         accumulator ^= static_cast<uint32_t>(operation.type);
     98         auto accumulateOperands = [&hidlModel, &accumulator](const hidl_vec<uint32_t>& operands) {
     99             for (uint32_t operandIndex : operands) {
    100                 const Operand& operand = hidlModel.operands[operandIndex];
    101                 accumulator ^= static_cast<uint32_t>(operand.type);
    102                 accumulator ^= operand.dimensions.size();
    103                 for (uint32_t dimension : operand.dimensions) {
    104                     accumulator ^= dimension;
    105                     if (operand.lifetime == OperandLifeTime::CONSTANT_COPY ||
    106                         operand.lifetime == OperandLifeTime::CONSTANT_REFERENCE) {
    107                         accumulator ^= 1;
    108                     }
    109                 }
    110             }
    111         };
    112         accumulateOperands(operation.inputs);
    113         accumulateOperands(operation.outputs);
    114         if (accumulator & 1) {
    115             (*outSupportedOperations)[operationIndex] = false;
    116         }
    117     }
    118 #endif  // NN_DEBUGGABLE
    119 }
    120 
    121 DeviceManager* DeviceManager::get() {
    122     static DeviceManager manager;
    123     return &manager;
    124 }
    125 
    126 void DeviceManager::findAvailableDevices() {
    127     using ::android::hardware::neuralnetworks::V1_0::IDevice;
    128     using ::android::hidl::manager::V1_0::IServiceManager;
    129     VLOG(MANAGER) << "findAvailableDevices";
    130 
    131     sp<IServiceManager> manager = hardware::defaultServiceManager();
    132     if (manager == nullptr) {
    133         LOG(ERROR) << "Unable to open defaultServiceManager";
    134         return;
    135     }
    136 
    137     manager->listByInterface(IDevice::descriptor, [this](const hidl_vec<hidl_string>& names) {
    138         for (const auto& name : names) {
    139             VLOG(MANAGER) << "Found interface " << name.c_str();
    140             sp<IDevice> device = IDevice::getService(name);
    141             if (device == nullptr) {
    142                 LOG(ERROR) << "Got a null IDEVICE for " << name.c_str();
    143                 continue;
    144             }
    145             registerDevice(name.c_str(), device);
    146         }
    147     });
    148 }
    149 
    150 void DeviceManager::registerDevice(const char* name, const sp<IDevice>& device) {
    151     auto d = std::make_shared<Device>(name, device);
    152     if (d->initialize()) {
    153         mDevices.push_back(d);
    154     }
    155 }
    156 
    157 DeviceManager::DeviceManager() {
    158     VLOG(MANAGER) << "DeviceManager::DeviceManager";
    159     findAvailableDevices();
    160 #ifdef NN_DEBUGGABLE
    161     mPartitioning = getProp("debug.nn.partition", kPartitioningDefault);
    162 #endif  // NN_DEBUGGABLE
    163 }
    164 
    165 }  // namespace nn
    166 }  // namespace android
    167