1 /*
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 
19 #include <AndroidVersionUtil.h>
20 #include <aidl/android/hardware/neuralnetworks/IDevice.h>
21 #include <android-base/logging.h>
22 #include <android/binder_manager.h>
23 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
24 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
25 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
26 #include <android/hardware/neuralnetworks/1.3/IDevice.h>
27 #include <android/hidl/manager/1.2/IServiceManager.h>
28 #include <hidl/ServiceManagement.h>
29 #include <nnapi/IDevice.h>
30 #include <nnapi/Result.h>
31 #include <nnapi/TypeUtils.h>
32 #include <nnapi/Types.h>
33 #include <nnapi/hal/1.0/Service.h>
34 #include <nnapi/hal/1.1/Service.h>
35 #include <nnapi/hal/1.2/Service.h>
36 #include <nnapi/hal/1.3/Service.h>
37 #include <nnapi/hal/aidl/Service.h>
38 #include <nnapi/hal/aidl/Utils.h>
39 
40 #include <functional>
41 #include <memory>
42 #include <string>
43 #include <type_traits>
44 #include <unordered_set>
45 #include <vector>
46 
47 namespace android::hardware::neuralnetworks::service {
48 namespace {
49 
50 namespace aidl_hal = ::aidl::android::hardware::neuralnetworks;
51 using getDeviceFn = std::add_pointer_t<nn::GeneralResult<nn::SharedDevice>(const std::string&)>;
52 
getHidlDevicesForVersion(const std::string & descriptor,getDeviceFn getDevice,std::vector<SharedDeviceAndUpdatability> * devices,std::unordered_set<std::string> * registeredDevices)53 void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice,
54                               std::vector<SharedDeviceAndUpdatability>* devices,
55                               std::unordered_set<std::string>* registeredDevices) {
56     CHECK(devices != nullptr);
57     CHECK(registeredDevices != nullptr);
58 
59     const auto names = getAllHalInstanceNames(descriptor);
60     for (const auto& name : names) {
61         if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
62             auto maybeDevice = getDevice(name);
63             if (maybeDevice.has_value()) {
64                 auto device = std::move(maybeDevice).value();
65                 CHECK(device != nullptr);
66                 devices->push_back({.device = std::move(device)});
67             } else {
68                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
69                            << ": " << maybeDevice.error().message;
70             }
71         }
72     }
73 }
74 
getAidlDevices(std::vector<SharedDeviceAndUpdatability> * devices,std::unordered_set<std::string> * registeredDevices,bool includeUpdatableDrivers)75 void getAidlDevices(std::vector<SharedDeviceAndUpdatability>* devices,
76                     std::unordered_set<std::string>* registeredDevices,
77                     bool includeUpdatableDrivers) {
78     CHECK(devices != nullptr);
79     CHECK(registeredDevices != nullptr);
80 
81     std::vector<std::string> names;
82     constexpr auto callback = [](const char* serviceName, void* names) {
83         static_cast<std::vector<std::string>*>(names)->emplace_back(serviceName);
84     };
85 
86     // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
87     // there is no need for a workaround supported on lower levels.
88     if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
89         AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
90                                                 static_cast<void*>(&names), callback);
91     }
92 
93     for (const auto& name : names) {
94         bool isDeviceUpdatable = false;
95         if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
96             const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name;
97             isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str());
98         }
99         if (isDeviceUpdatable && !includeUpdatableDrivers) {
100             continue;
101         }
102         if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) {
103             auto maybeDevice = aidl_hal::utils::getDevice(name);
104             if (maybeDevice.has_value()) {
105                 auto device = std::move(maybeDevice).value();
106                 CHECK(device != nullptr);
107                 devices->push_back(
108                         {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable});
109             } else {
110                 LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code
111                            << ": " << maybeDevice.error().message;
112             }
113         }
114     }
115 }
116 
117 }  // namespace
118 
getDevices(bool includeUpdatableDrivers)119 std::vector<SharedDeviceAndUpdatability> getDevices(bool includeUpdatableDrivers) {
120     std::vector<SharedDeviceAndUpdatability> devices;
121     std::unordered_set<std::string> registeredDevices;
122 
123     getAidlDevices(&devices, &registeredDevices, includeUpdatableDrivers);
124 
125     getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices,
126                              &registeredDevices);
127     getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices,
128                              &registeredDevices);
129     getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices,
130                              &registeredDevices);
131     getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices,
132                              &registeredDevices);
133 
134     return devices;
135 }
136 
137 }  // namespace android::hardware::neuralnetworks::service
138