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
Device(std::string name,const sp<V1_0::IDevice> & device)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
initialize()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
getSupportedOperations(const Model & hidlModel,hidl_vec<bool> * outSupportedOperations)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
get()128 DeviceManager* DeviceManager::get() {
129 static DeviceManager manager;
130 return &manager;
131 }
132
findAvailableDevices()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
registerDevice(const char * name,const sp<V1_0::IDevice> & device)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
DeviceManager()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