/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "Service.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace android::hardware::neuralnetworks::service { namespace { namespace aidl_hal = ::aidl::android::hardware::neuralnetworks; using getDeviceFn = std::add_pointer_t(const std::string&)>; void getHidlDevicesForVersion(const std::string& descriptor, getDeviceFn getDevice, std::vector* devices, std::unordered_set* registeredDevices) { CHECK(devices != nullptr); CHECK(registeredDevices != nullptr); const auto names = getAllHalInstanceNames(descriptor); for (const auto& name : names) { if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) { auto maybeDevice = getDevice(name); if (maybeDevice.has_value()) { auto device = std::move(maybeDevice).value(); CHECK(device != nullptr); devices->push_back({.device = std::move(device)}); } else { LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code << ": " << maybeDevice.error().message; } } } } void getAidlDevices(std::vector* devices, std::unordered_set* registeredDevices, bool includeUpdatableDrivers) { CHECK(devices != nullptr); CHECK(registeredDevices != nullptr); std::vector names; constexpr auto callback = [](const char* serviceName, void* names) { static_cast*>(names)->emplace_back(serviceName); }; // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so // there is no need for a workaround supported on lower levels. if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) { AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor, static_cast(&names), callback); } for (const auto& name : names) { bool isDeviceUpdatable = false; if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) { const auto instance = std::string(aidl_hal::IDevice::descriptor) + '/' + name; isDeviceUpdatable = AServiceManager_isUpdatableViaApex(instance.c_str()); } if (isDeviceUpdatable && !includeUpdatableDrivers) { continue; } if (const auto [it, unregistered] = registeredDevices->insert(name); unregistered) { auto maybeDevice = aidl_hal::utils::getDevice(name); if (maybeDevice.has_value()) { auto device = std::move(maybeDevice).value(); CHECK(device != nullptr); devices->push_back( {.device = std::move(device), .isDeviceUpdatable = isDeviceUpdatable}); } else { LOG(ERROR) << "getDevice(" << name << ") failed with " << maybeDevice.error().code << ": " << maybeDevice.error().message; } } } } } // namespace std::vector getDevices(bool includeUpdatableDrivers) { std::vector devices; std::unordered_set registeredDevices; getAidlDevices(&devices, ®isteredDevices, includeUpdatableDrivers); getHidlDevicesForVersion(V1_3::IDevice::descriptor, &V1_3::utils::getDevice, &devices, ®isteredDevices); getHidlDevicesForVersion(V1_2::IDevice::descriptor, &V1_2::utils::getDevice, &devices, ®isteredDevices); getHidlDevicesForVersion(V1_1::IDevice::descriptor, &V1_1::utils::getDevice, &devices, ®isteredDevices); getHidlDevicesForVersion(V1_0::IDevice::descriptor, &V1_0::utils::getDevice, &devices, ®isteredDevices); return devices; } } // namespace android::hardware::neuralnetworks::service