1*33f37583SAndroid Build Coastguard Worker /*
2*33f37583SAndroid Build Coastguard Worker * Copyright (C) 2023 The Android Open Source Project
3*33f37583SAndroid Build Coastguard Worker *
4*33f37583SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*33f37583SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*33f37583SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*33f37583SAndroid Build Coastguard Worker *
8*33f37583SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*33f37583SAndroid Build Coastguard Worker *
10*33f37583SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*33f37583SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*33f37583SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*33f37583SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*33f37583SAndroid Build Coastguard Worker * limitations under the License.
15*33f37583SAndroid Build Coastguard Worker *
16*33f37583SAndroid Build Coastguard Worker * This file contains the vendor-apex-specific functions of apexd
17*33f37583SAndroid Build Coastguard Worker */
18*33f37583SAndroid Build Coastguard Worker
19*33f37583SAndroid Build Coastguard Worker #include "apexd_vendor_apex.h"
20*33f37583SAndroid Build Coastguard Worker
21*33f37583SAndroid Build Coastguard Worker #include <android-base/logging.h>
22*33f37583SAndroid Build Coastguard Worker #include <android-base/strings.h>
23*33f37583SAndroid Build Coastguard Worker #include <vintf/VintfObject.h>
24*33f37583SAndroid Build Coastguard Worker
25*33f37583SAndroid Build Coastguard Worker #include "apex_file_repository.h"
26*33f37583SAndroid Build Coastguard Worker #include "apexd_private.h"
27*33f37583SAndroid Build Coastguard Worker #include "apexd_utils.h"
28*33f37583SAndroid Build Coastguard Worker
29*33f37583SAndroid Build Coastguard Worker using android::base::Error;
30*33f37583SAndroid Build Coastguard Worker using android::base::Result;
31*33f37583SAndroid Build Coastguard Worker using android::base::StartsWith;
32*33f37583SAndroid Build Coastguard Worker
33*33f37583SAndroid Build Coastguard Worker namespace android::apex {
34*33f37583SAndroid Build Coastguard Worker
35*33f37583SAndroid Build Coastguard Worker using apexd_private::GetActiveMountPoint;
36*33f37583SAndroid Build Coastguard Worker
HasVintfIn(std::span<const std::string> apex_mounts)37*33f37583SAndroid Build Coastguard Worker static Result<bool> HasVintfIn(std::span<const std::string> apex_mounts) {
38*33f37583SAndroid Build Coastguard Worker for (const auto& mount : apex_mounts) {
39*33f37583SAndroid Build Coastguard Worker if (OR_RETURN(PathExists(mount + "/etc/vintf"))) return true;
40*33f37583SAndroid Build Coastguard Worker }
41*33f37583SAndroid Build Coastguard Worker return false;
42*33f37583SAndroid Build Coastguard Worker }
43*33f37583SAndroid Build Coastguard Worker
44*33f37583SAndroid Build Coastguard Worker // Checks Compatibility for incoming APEXes.
45*33f37583SAndroid Build Coastguard Worker // Adds the data from apex's vintf_fragment(s) and tests compatibility.
CheckVintf(std::span<const ApexFile> apex_files,std::span<const std::string> mount_points)46*33f37583SAndroid Build Coastguard Worker Result<std::map<std::string, std::vector<std::string>>> CheckVintf(
47*33f37583SAndroid Build Coastguard Worker std::span<const ApexFile> apex_files,
48*33f37583SAndroid Build Coastguard Worker std::span<const std::string> mount_points) {
49*33f37583SAndroid Build Coastguard Worker std::string error;
50*33f37583SAndroid Build Coastguard Worker
51*33f37583SAndroid Build Coastguard Worker std::vector<std::string> current_mounts;
52*33f37583SAndroid Build Coastguard Worker for (const auto& apex : apex_files) {
53*33f37583SAndroid Build Coastguard Worker current_mounts.push_back(GetActiveMountPoint(apex.GetManifest()));
54*33f37583SAndroid Build Coastguard Worker }
55*33f37583SAndroid Build Coastguard Worker
56*33f37583SAndroid Build Coastguard Worker // Skip the check unless any of the current/incoming APEXes has etc/vintf.
57*33f37583SAndroid Build Coastguard Worker if (!OR_RETURN(HasVintfIn(current_mounts)) &&
58*33f37583SAndroid Build Coastguard Worker !OR_RETURN(HasVintfIn(mount_points))) {
59*33f37583SAndroid Build Coastguard Worker return {};
60*33f37583SAndroid Build Coastguard Worker }
61*33f37583SAndroid Build Coastguard Worker
62*33f37583SAndroid Build Coastguard Worker // Create PathReplacingFileSystem instance containing caller's path
63*33f37583SAndroid Build Coastguard Worker // substitutions
64*33f37583SAndroid Build Coastguard Worker std::map<std::string, std::string> replacements;
65*33f37583SAndroid Build Coastguard Worker CHECK(apex_files.size() == mount_points.size()) << "size mismatch";
66*33f37583SAndroid Build Coastguard Worker for (size_t i = 0; i < current_mounts.size(); i++) {
67*33f37583SAndroid Build Coastguard Worker replacements.emplace(current_mounts[i], mount_points[i]);
68*33f37583SAndroid Build Coastguard Worker }
69*33f37583SAndroid Build Coastguard Worker std::unique_ptr<vintf::FileSystem> path_replaced_fs =
70*33f37583SAndroid Build Coastguard Worker std::make_unique<vintf::details::PathReplacingFileSystem>(
71*33f37583SAndroid Build Coastguard Worker std::make_unique<vintf::details::FileSystemImpl>(),
72*33f37583SAndroid Build Coastguard Worker std::move(replacements));
73*33f37583SAndroid Build Coastguard Worker
74*33f37583SAndroid Build Coastguard Worker // Create a new VintfObject that uses our path-replacing FileSystem instance
75*33f37583SAndroid Build Coastguard Worker auto vintf_object = vintf::VintfObject::Builder()
76*33f37583SAndroid Build Coastguard Worker .setFileSystem(std::move(path_replaced_fs))
77*33f37583SAndroid Build Coastguard Worker .build();
78*33f37583SAndroid Build Coastguard Worker
79*33f37583SAndroid Build Coastguard Worker // Disable RuntimeInfo components. Allows callers to run check
80*33f37583SAndroid Build Coastguard Worker // without requiring read permission of restricted resources
81*33f37583SAndroid Build Coastguard Worker auto flags = vintf::CheckFlags::DEFAULT;
82*33f37583SAndroid Build Coastguard Worker flags = flags.disableRuntimeInfo();
83*33f37583SAndroid Build Coastguard Worker
84*33f37583SAndroid Build Coastguard Worker // checkCompatibility on vintfObj using the replacement vintf directory
85*33f37583SAndroid Build Coastguard Worker int ret = vintf_object->checkCompatibility(&error, flags);
86*33f37583SAndroid Build Coastguard Worker if (ret == vintf::INCOMPATIBLE) {
87*33f37583SAndroid Build Coastguard Worker return Error() << "CheckVintf failed: not compatible. error=" << error;
88*33f37583SAndroid Build Coastguard Worker }
89*33f37583SAndroid Build Coastguard Worker if (ret != vintf::COMPATIBLE) {
90*33f37583SAndroid Build Coastguard Worker return Error() << "CheckVintf failed: error=" << error;
91*33f37583SAndroid Build Coastguard Worker }
92*33f37583SAndroid Build Coastguard Worker
93*33f37583SAndroid Build Coastguard Worker // Compat check passed.
94*33f37583SAndroid Build Coastguard Worker // Collect HAL information from incoming APEXes for metrics.
95*33f37583SAndroid Build Coastguard Worker std::map<std::string, std::vector<std::string>> apex_hals;
96*33f37583SAndroid Build Coastguard Worker auto collect_hals = [&](auto manifest) {
97*33f37583SAndroid Build Coastguard Worker manifest->forEachInstance([&](const auto& instance) {
98*33f37583SAndroid Build Coastguard Worker if (instance.updatableViaApex().has_value()) {
99*33f37583SAndroid Build Coastguard Worker apex_hals[instance.updatableViaApex().value()].push_back(
100*33f37583SAndroid Build Coastguard Worker instance.nameWithVersion());
101*33f37583SAndroid Build Coastguard Worker }
102*33f37583SAndroid Build Coastguard Worker return true; // continue
103*33f37583SAndroid Build Coastguard Worker });
104*33f37583SAndroid Build Coastguard Worker };
105*33f37583SAndroid Build Coastguard Worker collect_hals(vintf_object->getFrameworkHalManifest());
106*33f37583SAndroid Build Coastguard Worker collect_hals(vintf_object->getDeviceHalManifest());
107*33f37583SAndroid Build Coastguard Worker
108*33f37583SAndroid Build Coastguard Worker return apex_hals;
109*33f37583SAndroid Build Coastguard Worker }
110*33f37583SAndroid Build Coastguard Worker
111*33f37583SAndroid Build Coastguard Worker } // namespace android::apex
112