blob: c83bcc916cee6e115d48b5b78a15e143abb3859d [file] [log] [blame]
Michael Butler4b276a72020-08-06 23:22:35 -07001/*
2 * Copyright (C) 2020 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#include "Service.h"
18
Lev Proleev2d7195f2021-02-16 12:58:16 +000019#include <aidl/android/hardware/neuralnetworks/IDevice.h>
Michael Butler4b276a72020-08-06 23:22:35 -070020#include <android-base/logging.h>
Lev Proleev2d7195f2021-02-16 12:58:16 +000021#include <android/binder_manager.h>
Michael Butler4b276a72020-08-06 23:22:35 -070022#include <android/hardware/neuralnetworks/1.0/IDevice.h>
23#include <android/hardware/neuralnetworks/1.1/IDevice.h>
24#include <android/hardware/neuralnetworks/1.2/IDevice.h>
25#include <android/hardware/neuralnetworks/1.3/IDevice.h>
26#include <android/hidl/manager/1.2/IServiceManager.h>
27#include <hidl/ServiceManagement.h>
28#include <nnapi/IDevice.h>
29#include <nnapi/Result.h>
30#include <nnapi/TypeUtils.h>
31#include <nnapi/Types.h>
32#include <nnapi/hal/1.0/Service.h>
33#include <nnapi/hal/1.1/Service.h>
34#include <nnapi/hal/1.2/Service.h>
35#include <nnapi/hal/1.3/Service.h>
Lev Proleev2d7195f2021-02-16 12:58:16 +000036#include <nnapi/hal/aidl/Service.h>
Michael Butler4b276a72020-08-06 23:22:35 -070037
38#include <functional>
39#include <memory>
40#include <string>
41#include <type_traits>
42#include <unordered_set>
43#include <vector>
44
45namespace android::hardware::neuralnetworks::service {
46namespace {
47
Lev Proleev2d7195f2021-02-16 12:58:16 +000048namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
Michael Butler4b276a72020-08-06 23:22:35 -070049using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
50
Lev Proleev2d7195f2021-02-16 12:58:16 +000051void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
52 std::vector<nn::SharedDevice>* devices,
53 std::unordered_set<std::string>* registeredDevices) {
Michael Butler4b276a72020-08-06 23:22:35 -070054 CHECK(devices != nullptr);
55 CHECK(registeredDevices != nullptr);
56
57 const auto names = getAllHalInstanceNames(descriptor);
58 for (const auto& name : names) {
59 if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
60 auto maybeDevice = getDevice(name);
61 if (maybeDevice.has_value()) {
62 auto device = std::move(maybeDevice).value();
63 CHECK(device != nullptr);
64 devices->push_back(std::move(device));
65 } else {
66 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
67 << ": " << maybeDevice.error().message;
68 }
69 }
70 }
71}
72
Lev Proleev2d7195f2021-02-16 12:58:16 +000073void getAidlDevices(std::vector<nn::SharedDevice>* devices,
74 std::unordered_set<std::string>* registeredDevices) {
75 CHECK(devices != nullptr);
76 CHECK(registeredDevices != nullptr);
77
78 std::vector<std::string> names;
79 constexpr auto callback = [](const char* serviceName, void* names) {
80 static_cast<std::vector<std::string>*>(names)->emplace_back(serviceName);
81 };
82
83 // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
84 // there is no need for a workaround supported on lower levels.
85 if (__builtin_available(android __ANDROID_API_S__, *)) {
86 AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
87 static_cast<void*>(&names), callback);
88 }
89
90 for (const auto& name : names) {
91 if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
92 auto maybeDevice = aidl_hal::utils::getDevice(name);
93 if (maybeDevice.has_value()) {
94 auto device = std::move(maybeDevice).value();
95 CHECK(device != nullptr);
96 devices->push_back(std::move(device));
97 } else {
98 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
99 << ": " << maybeDevice.error().message;
100 }
101 }
102 }
103}
104
Michael Butler4b276a72020-08-06 23:22:35 -0700105std::vector<nn::SharedDevice> getDevices() {
106 std::vector<nn::SharedDevice> devices;
107 std::unordered_set<std::string> registeredDevices;
108
Lev Proleev2d7195f2021-02-16 12:58:16 +0000109 getAidlDevices(&devices, &registeredDevices);
110
111 getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
112 &registeredDevices);
113 getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
114 &registeredDevices);
115 getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
116 &registeredDevices);
117 getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
118 &registeredDevices);
Michael Butler4b276a72020-08-06 23:22:35 -0700119
120 return devices;
121}
122
123} // namespace
124} // namespace android::hardware::neuralnetworks::service
125
126namespace android::nn::hal {
127
128std::vector<nn::SharedDevice> getDevices() {
129 return hardware::neuralnetworks::service::getDevices();
130}
131
132} // namespace android::nn::hal