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