1 /*
2 * Copyright (C) 2023 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 * This file contains the vendor-apex-specific functions of apexd
17 */
18
19 #include "apexd_vendor_apex.h"
20
21 #include <android-base/logging.h>
22 #include <android-base/strings.h>
23 #include <vintf/VintfObject.h>
24
25 #include "apex_file_repository.h"
26 #include "apexd_private.h"
27 #include "apexd_utils.h"
28
29 using android::base::Error;
30 using android::base::Result;
31 using android::base::StartsWith;
32
33 namespace android::apex {
34
35 using apexd_private::GetActiveMountPoint;
36
HasVintfIn(std::span<const std::string> apex_mounts)37 static Result<bool> HasVintfIn(std::span<const std::string> apex_mounts) {
38 for (const auto& mount : apex_mounts) {
39 if (OR_RETURN(PathExists(mount + "/etc/vintf"))) return true;
40 }
41 return false;
42 }
43
44 // Checks Compatibility for incoming APEXes.
45 // 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 Result<std::map<std::string, std::vector<std::string>>> CheckVintf(
47 std::span<const ApexFile> apex_files,
48 std::span<const std::string> mount_points) {
49 std::string error;
50
51 std::vector<std::string> current_mounts;
52 for (const auto& apex : apex_files) {
53 current_mounts.push_back(GetActiveMountPoint(apex.GetManifest()));
54 }
55
56 // Skip the check unless any of the current/incoming APEXes has etc/vintf.
57 if (!OR_RETURN(HasVintfIn(current_mounts)) &&
58 !OR_RETURN(HasVintfIn(mount_points))) {
59 return {};
60 }
61
62 // Create PathReplacingFileSystem instance containing caller's path
63 // substitutions
64 std::map<std::string, std::string> replacements;
65 CHECK(apex_files.size() == mount_points.size()) << "size mismatch";
66 for (size_t i = 0; i < current_mounts.size(); i++) {
67 replacements.emplace(current_mounts[i], mount_points[i]);
68 }
69 std::unique_ptr<vintf::FileSystem> path_replaced_fs =
70 std::make_unique<vintf::details::PathReplacingFileSystem>(
71 std::make_unique<vintf::details::FileSystemImpl>(),
72 std::move(replacements));
73
74 // Create a new VintfObject that uses our path-replacing FileSystem instance
75 auto vintf_object = vintf::VintfObject::Builder()
76 .setFileSystem(std::move(path_replaced_fs))
77 .build();
78
79 // Disable RuntimeInfo components. Allows callers to run check
80 // without requiring read permission of restricted resources
81 auto flags = vintf::CheckFlags::DEFAULT;
82 flags = flags.disableRuntimeInfo();
83
84 // checkCompatibility on vintfObj using the replacement vintf directory
85 int ret = vintf_object->checkCompatibility(&error, flags);
86 if (ret == vintf::INCOMPATIBLE) {
87 return Error() << "CheckVintf failed: not compatible. error=" << error;
88 }
89 if (ret != vintf::COMPATIBLE) {
90 return Error() << "CheckVintf failed: error=" << error;
91 }
92
93 // Compat check passed.
94 // Collect HAL information from incoming APEXes for metrics.
95 std::map<std::string, std::vector<std::string>> apex_hals;
96 auto collect_hals = [&](auto manifest) {
97 manifest->forEachInstance([&](const auto& instance) {
98 if (instance.updatableViaApex().has_value()) {
99 apex_hals[instance.updatableViaApex().value()].push_back(
100 instance.nameWithVersion());
101 }
102 return true; // continue
103 });
104 };
105 collect_hals(vintf_object->getFrameworkHalManifest());
106 collect_hals(vintf_object->getDeviceHalManifest());
107
108 return apex_hals;
109 }
110
111 } // namespace android::apex
112