/* * Copyright (C) 2023 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. * * This file contains the vendor-apex-specific functions of apexd */ #include "apexd_vendor_apex.h" #include #include #include #include "apex_file_repository.h" #include "apexd_private.h" #include "apexd_utils.h" using android::base::Error; using android::base::Result; using android::base::StartsWith; namespace android::apex { using apexd_private::GetActiveMountPoint; static Result HasVintfIn(std::span apex_mounts) { for (const auto& mount : apex_mounts) { if (OR_RETURN(PathExists(mount + "/etc/vintf"))) return true; } return false; } // Checks Compatibility for incoming APEXes. // Adds the data from apex's vintf_fragment(s) and tests compatibility. Result>> CheckVintf( std::span apex_files, std::span mount_points) { std::string error; std::vector current_mounts; for (const auto& apex : apex_files) { current_mounts.push_back(GetActiveMountPoint(apex.GetManifest())); } // Skip the check unless any of the current/incoming APEXes has etc/vintf. if (!OR_RETURN(HasVintfIn(current_mounts)) && !OR_RETURN(HasVintfIn(mount_points))) { return {}; } // Create PathReplacingFileSystem instance containing caller's path // substitutions std::map replacements; CHECK(apex_files.size() == mount_points.size()) << "size mismatch"; for (size_t i = 0; i < current_mounts.size(); i++) { replacements.emplace(current_mounts[i], mount_points[i]); } std::unique_ptr path_replaced_fs = std::make_unique( std::make_unique(), std::move(replacements)); // Create a new VintfObject that uses our path-replacing FileSystem instance auto vintf_object = vintf::VintfObject::Builder() .setFileSystem(std::move(path_replaced_fs)) .build(); // Disable RuntimeInfo components. Allows callers to run check // without requiring read permission of restricted resources auto flags = vintf::CheckFlags::DEFAULT; flags = flags.disableRuntimeInfo(); // checkCompatibility on vintfObj using the replacement vintf directory int ret = vintf_object->checkCompatibility(&error, flags); if (ret == vintf::INCOMPATIBLE) { return Error() << "CheckVintf failed: not compatible. error=" << error; } if (ret != vintf::COMPATIBLE) { return Error() << "CheckVintf failed: error=" << error; } // Compat check passed. // Collect HAL information from incoming APEXes for metrics. std::map> apex_hals; auto collect_hals = [&](auto manifest) { manifest->forEachInstance([&](const auto& instance) { if (instance.updatableViaApex().has_value()) { apex_hals[instance.updatableViaApex().value()].push_back( instance.nameWithVersion()); } return true; // continue }); }; collect_hals(vintf_object->getFrameworkHalManifest()); collect_hals(vintf_object->getDeviceHalManifest()); return apex_hals; } } // namespace android::apex