1*e5eeaa8eSAndroid Build Coastguard Worker /*
2*e5eeaa8eSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*e5eeaa8eSAndroid Build Coastguard Worker *
4*e5eeaa8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e5eeaa8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e5eeaa8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e5eeaa8eSAndroid Build Coastguard Worker *
8*e5eeaa8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e5eeaa8eSAndroid Build Coastguard Worker *
10*e5eeaa8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e5eeaa8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e5eeaa8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e5eeaa8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e5eeaa8eSAndroid Build Coastguard Worker * limitations under the License.
15*e5eeaa8eSAndroid Build Coastguard Worker */
16*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/apex.h"
17*e5eeaa8eSAndroid Build Coastguard Worker
18*e5eeaa8eSAndroid Build Coastguard Worker #include <algorithm>
19*e5eeaa8eSAndroid Build Coastguard Worker #include <cstring>
20*e5eeaa8eSAndroid Build Coastguard Worker #include <regex>
21*e5eeaa8eSAndroid Build Coastguard Worker #include <set>
22*e5eeaa8eSAndroid Build Coastguard Worker #include <string>
23*e5eeaa8eSAndroid Build Coastguard Worker #include <string_view>
24*e5eeaa8eSAndroid Build Coastguard Worker #include <vector>
25*e5eeaa8eSAndroid Build Coastguard Worker
26*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/file.h>
27*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/result.h>
28*e5eeaa8eSAndroid Build Coastguard Worker #include <android-base/strings.h>
29*e5eeaa8eSAndroid Build Coastguard Worker #include <apexutil.h>
30*e5eeaa8eSAndroid Build Coastguard Worker #include <unistd.h>
31*e5eeaa8eSAndroid Build Coastguard Worker
32*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/configparser.h"
33*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/environment.h"
34*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/log.h"
35*e5eeaa8eSAndroid Build Coastguard Worker #include "linkerconfig/stringutil.h"
36*e5eeaa8eSAndroid Build Coastguard Worker
37*e5eeaa8eSAndroid Build Coastguard Worker // include after log.h to avoid macro redefinition error
38*e5eeaa8eSAndroid Build Coastguard Worker #include "com_android_apex.h"
39*e5eeaa8eSAndroid Build Coastguard Worker
40*e5eeaa8eSAndroid Build Coastguard Worker using android::base::ErrnoError;
41*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Error;
42*e5eeaa8eSAndroid Build Coastguard Worker using android::base::ReadFileToString;
43*e5eeaa8eSAndroid Build Coastguard Worker using android::base::Result;
44*e5eeaa8eSAndroid Build Coastguard Worker using android::base::StartsWith;
45*e5eeaa8eSAndroid Build Coastguard Worker
46*e5eeaa8eSAndroid Build Coastguard Worker namespace {
PathExists(const std::string & path)47*e5eeaa8eSAndroid Build Coastguard Worker bool PathExists(const std::string& path) {
48*e5eeaa8eSAndroid Build Coastguard Worker return access(path.c_str(), F_OK) == 0;
49*e5eeaa8eSAndroid Build Coastguard Worker }
50*e5eeaa8eSAndroid Build Coastguard Worker
ReadPublicLibraries(const std::string & filepath)51*e5eeaa8eSAndroid Build Coastguard Worker Result<std::set<std::string>> ReadPublicLibraries(const std::string& filepath) {
52*e5eeaa8eSAndroid Build Coastguard Worker std::string file_content;
53*e5eeaa8eSAndroid Build Coastguard Worker if (!android::base::ReadFileToString(filepath, &file_content, true)) {
54*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError();
55*e5eeaa8eSAndroid Build Coastguard Worker }
56*e5eeaa8eSAndroid Build Coastguard Worker std::vector<std::string> lines = android::base::Split(file_content, "\n");
57*e5eeaa8eSAndroid Build Coastguard Worker std::set<std::string> sonames;
58*e5eeaa8eSAndroid Build Coastguard Worker for (auto& line : lines) {
59*e5eeaa8eSAndroid Build Coastguard Worker auto trimmed_line = android::base::Trim(line);
60*e5eeaa8eSAndroid Build Coastguard Worker if (trimmed_line.empty() || trimmed_line[0] == '#') {
61*e5eeaa8eSAndroid Build Coastguard Worker continue;
62*e5eeaa8eSAndroid Build Coastguard Worker }
63*e5eeaa8eSAndroid Build Coastguard Worker std::vector<std::string> tokens = android::base::Split(trimmed_line, " ");
64*e5eeaa8eSAndroid Build Coastguard Worker if (tokens.size() < 1 || tokens.size() > 3) {
65*e5eeaa8eSAndroid Build Coastguard Worker return Errorf("Malformed line \"{}\"", line);
66*e5eeaa8eSAndroid Build Coastguard Worker }
67*e5eeaa8eSAndroid Build Coastguard Worker sonames.insert(tokens[0]);
68*e5eeaa8eSAndroid Build Coastguard Worker }
69*e5eeaa8eSAndroid Build Coastguard Worker return sonames;
70*e5eeaa8eSAndroid Build Coastguard Worker }
71*e5eeaa8eSAndroid Build Coastguard Worker
Intersect(const std::vector<std::string> & as,const std::set<std::string> & bs)72*e5eeaa8eSAndroid Build Coastguard Worker std::vector<std::string> Intersect(const std::vector<std::string>& as,
73*e5eeaa8eSAndroid Build Coastguard Worker const std::set<std::string>& bs) {
74*e5eeaa8eSAndroid Build Coastguard Worker std::vector<std::string> intersect;
75*e5eeaa8eSAndroid Build Coastguard Worker std::copy_if(as.begin(),
76*e5eeaa8eSAndroid Build Coastguard Worker as.end(),
77*e5eeaa8eSAndroid Build Coastguard Worker std::back_inserter(intersect),
78*e5eeaa8eSAndroid Build Coastguard Worker [&bs](const auto& a) { return bs.find(a) != bs.end(); });
79*e5eeaa8eSAndroid Build Coastguard Worker return intersect;
80*e5eeaa8eSAndroid Build Coastguard Worker }
81*e5eeaa8eSAndroid Build Coastguard Worker
IsValidForPath(const uint_fast8_t c)82*e5eeaa8eSAndroid Build Coastguard Worker bool IsValidForPath(const uint_fast8_t c) {
83*e5eeaa8eSAndroid Build Coastguard Worker if (c >= 'a' && c <= 'z') return true;
84*e5eeaa8eSAndroid Build Coastguard Worker if (c >= 'A' && c <= 'Z') return true;
85*e5eeaa8eSAndroid Build Coastguard Worker if (c >= '0' && c <= '9') return true;
86*e5eeaa8eSAndroid Build Coastguard Worker if (c == '-' || c == '_' || c == '.') return true;
87*e5eeaa8eSAndroid Build Coastguard Worker return false;
88*e5eeaa8eSAndroid Build Coastguard Worker }
89*e5eeaa8eSAndroid Build Coastguard Worker
VerifyPath(const std::string & path)90*e5eeaa8eSAndroid Build Coastguard Worker Result<void> VerifyPath(const std::string& path) {
91*e5eeaa8eSAndroid Build Coastguard Worker const size_t length = path.length();
92*e5eeaa8eSAndroid Build Coastguard Worker constexpr char lib_dir[] = "${LIB}";
93*e5eeaa8eSAndroid Build Coastguard Worker constexpr size_t lib_dir_len = (sizeof lib_dir) - 1;
94*e5eeaa8eSAndroid Build Coastguard Worker const std::string_view path_view(path);
95*e5eeaa8eSAndroid Build Coastguard Worker
96*e5eeaa8eSAndroid Build Coastguard Worker if (length == 0) {
97*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Empty path is not allowed";
98*e5eeaa8eSAndroid Build Coastguard Worker }
99*e5eeaa8eSAndroid Build Coastguard Worker
100*e5eeaa8eSAndroid Build Coastguard Worker for (size_t i = 0; i < length; i++) {
101*e5eeaa8eSAndroid Build Coastguard Worker uint_fast8_t current_char = path[i];
102*e5eeaa8eSAndroid Build Coastguard Worker if (current_char == '/') {
103*e5eeaa8eSAndroid Build Coastguard Worker i++;
104*e5eeaa8eSAndroid Build Coastguard Worker if (i >= length) {
105*e5eeaa8eSAndroid Build Coastguard Worker return {};
106*e5eeaa8eSAndroid Build Coastguard Worker } else if (path[i] == '/') {
107*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "'/' should not appear twice in " << path;
108*e5eeaa8eSAndroid Build Coastguard Worker } else if (i + lib_dir_len <= length &&
109*e5eeaa8eSAndroid Build Coastguard Worker path_view.substr(i, lib_dir_len) == lib_dir) {
110*e5eeaa8eSAndroid Build Coastguard Worker i += lib_dir_len - 1;
111*e5eeaa8eSAndroid Build Coastguard Worker } else {
112*e5eeaa8eSAndroid Build Coastguard Worker for (; i < length; i++) {
113*e5eeaa8eSAndroid Build Coastguard Worker current_char = path[i];
114*e5eeaa8eSAndroid Build Coastguard Worker if (current_char == '/') {
115*e5eeaa8eSAndroid Build Coastguard Worker i--;
116*e5eeaa8eSAndroid Build Coastguard Worker break;
117*e5eeaa8eSAndroid Build Coastguard Worker }
118*e5eeaa8eSAndroid Build Coastguard Worker
119*e5eeaa8eSAndroid Build Coastguard Worker if (!IsValidForPath(current_char)) {
120*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Invalid char '" << current_char << "' in "
121*e5eeaa8eSAndroid Build Coastguard Worker << path;
122*e5eeaa8eSAndroid Build Coastguard Worker }
123*e5eeaa8eSAndroid Build Coastguard Worker }
124*e5eeaa8eSAndroid Build Coastguard Worker }
125*e5eeaa8eSAndroid Build Coastguard Worker } else {
126*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Invalid char '" << current_char << "' in " << path
127*e5eeaa8eSAndroid Build Coastguard Worker << " at " << i;
128*e5eeaa8eSAndroid Build Coastguard Worker }
129*e5eeaa8eSAndroid Build Coastguard Worker }
130*e5eeaa8eSAndroid Build Coastguard Worker
131*e5eeaa8eSAndroid Build Coastguard Worker return {};
132*e5eeaa8eSAndroid Build Coastguard Worker }
133*e5eeaa8eSAndroid Build Coastguard Worker
ReadPublicLibrariesOpt(const std::string & filepath)134*e5eeaa8eSAndroid Build Coastguard Worker Result<std::set<std::string>> ReadPublicLibrariesOpt(const std::string& filepath) {
135*e5eeaa8eSAndroid Build Coastguard Worker // Do not fail when public.libraries.txt is missing for minimal Android
136*e5eeaa8eSAndroid Build Coastguard Worker // environment with no ART.
137*e5eeaa8eSAndroid Build Coastguard Worker if (!PathExists(filepath)) {
138*e5eeaa8eSAndroid Build Coastguard Worker return {};
139*e5eeaa8eSAndroid Build Coastguard Worker }
140*e5eeaa8eSAndroid Build Coastguard Worker // But fails with error while reading the file
141*e5eeaa8eSAndroid Build Coastguard Worker auto public_libraries = ReadPublicLibraries(filepath);
142*e5eeaa8eSAndroid Build Coastguard Worker if (!public_libraries.ok()) {
143*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Can't read " << filepath << ": "
144*e5eeaa8eSAndroid Build Coastguard Worker << public_libraries.error();
145*e5eeaa8eSAndroid Build Coastguard Worker }
146*e5eeaa8eSAndroid Build Coastguard Worker return public_libraries;
147*e5eeaa8eSAndroid Build Coastguard Worker }
148*e5eeaa8eSAndroid Build Coastguard Worker } // namespace
149*e5eeaa8eSAndroid Build Coastguard Worker
150*e5eeaa8eSAndroid Build Coastguard Worker namespace android {
151*e5eeaa8eSAndroid Build Coastguard Worker namespace linkerconfig {
152*e5eeaa8eSAndroid Build Coastguard Worker namespace modules {
153*e5eeaa8eSAndroid Build Coastguard Worker
ScanActiveApexes(const std::string & root)154*e5eeaa8eSAndroid Build Coastguard Worker Result<std::map<std::string, ApexInfo>> ScanActiveApexes(const std::string& root) {
155*e5eeaa8eSAndroid Build Coastguard Worker std::map<std::string, ApexInfo> apexes;
156*e5eeaa8eSAndroid Build Coastguard Worker const auto apex_root = root + apex::kApexRoot;
157*e5eeaa8eSAndroid Build Coastguard Worker for (const auto& [path, manifest] : apex::GetActivePackages(apex_root)) {
158*e5eeaa8eSAndroid Build Coastguard Worker bool has_bin = PathExists(path + "/bin");
159*e5eeaa8eSAndroid Build Coastguard Worker bool has_lib = PathExists(path + "/lib") || PathExists(path + "/lib64");
160*e5eeaa8eSAndroid Build Coastguard Worker bool has_shared_lib = manifest.requiresharedapexlibs().size() != 0;
161*e5eeaa8eSAndroid Build Coastguard Worker
162*e5eeaa8eSAndroid Build Coastguard Worker std::vector<std::string> permitted_paths;
163*e5eeaa8eSAndroid Build Coastguard Worker bool visible = false;
164*e5eeaa8eSAndroid Build Coastguard Worker
165*e5eeaa8eSAndroid Build Coastguard Worker std::string linker_config_path = path + "/etc/linker.config.pb";
166*e5eeaa8eSAndroid Build Coastguard Worker if (PathExists(linker_config_path)) {
167*e5eeaa8eSAndroid Build Coastguard Worker auto linker_config = ParseLinkerConfig(linker_config_path);
168*e5eeaa8eSAndroid Build Coastguard Worker
169*e5eeaa8eSAndroid Build Coastguard Worker if (linker_config.ok()) {
170*e5eeaa8eSAndroid Build Coastguard Worker permitted_paths = {linker_config->permittedpaths().begin(),
171*e5eeaa8eSAndroid Build Coastguard Worker linker_config->permittedpaths().end()};
172*e5eeaa8eSAndroid Build Coastguard Worker for (const std::string& path : permitted_paths) {
173*e5eeaa8eSAndroid Build Coastguard Worker Result<void> verify_permitted_path = VerifyPath(path);
174*e5eeaa8eSAndroid Build Coastguard Worker if (!verify_permitted_path.ok()) {
175*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Failed to validate path from APEX linker config"
176*e5eeaa8eSAndroid Build Coastguard Worker << linker_config_path << " : "
177*e5eeaa8eSAndroid Build Coastguard Worker << verify_permitted_path.error();
178*e5eeaa8eSAndroid Build Coastguard Worker }
179*e5eeaa8eSAndroid Build Coastguard Worker }
180*e5eeaa8eSAndroid Build Coastguard Worker visible = linker_config->visible();
181*e5eeaa8eSAndroid Build Coastguard Worker } else {
182*e5eeaa8eSAndroid Build Coastguard Worker return Error() << "Failed to read APEX linker config : "
183*e5eeaa8eSAndroid Build Coastguard Worker << linker_config.error();
184*e5eeaa8eSAndroid Build Coastguard Worker }
185*e5eeaa8eSAndroid Build Coastguard Worker }
186*e5eeaa8eSAndroid Build Coastguard Worker
187*e5eeaa8eSAndroid Build Coastguard Worker ApexInfo info(manifest.name(),
188*e5eeaa8eSAndroid Build Coastguard Worker TrimPrefix(path, root),
189*e5eeaa8eSAndroid Build Coastguard Worker {manifest.providenativelibs().begin(),
190*e5eeaa8eSAndroid Build Coastguard Worker manifest.providenativelibs().end()},
191*e5eeaa8eSAndroid Build Coastguard Worker {manifest.requirenativelibs().begin(),
192*e5eeaa8eSAndroid Build Coastguard Worker manifest.requirenativelibs().end()},
193*e5eeaa8eSAndroid Build Coastguard Worker {manifest.jnilibs().begin(), manifest.jnilibs().end()},
194*e5eeaa8eSAndroid Build Coastguard Worker std::move(permitted_paths),
195*e5eeaa8eSAndroid Build Coastguard Worker has_bin,
196*e5eeaa8eSAndroid Build Coastguard Worker has_lib,
197*e5eeaa8eSAndroid Build Coastguard Worker visible,
198*e5eeaa8eSAndroid Build Coastguard Worker has_shared_lib);
199*e5eeaa8eSAndroid Build Coastguard Worker apexes.emplace(manifest.name(), std::move(info));
200*e5eeaa8eSAndroid Build Coastguard Worker }
201*e5eeaa8eSAndroid Build Coastguard Worker
202*e5eeaa8eSAndroid Build Coastguard Worker // After scanning apexes, we still need to augment ApexInfo based on other
203*e5eeaa8eSAndroid Build Coastguard Worker // input files
204*e5eeaa8eSAndroid Build Coastguard Worker // - original_path: based on /apex/apex-info-list.xml
205*e5eeaa8eSAndroid Build Coastguard Worker // - public_libs: based on /{system, vendor}/etc/public.libraries.txt
206*e5eeaa8eSAndroid Build Coastguard Worker
207*e5eeaa8eSAndroid Build Coastguard Worker if (!apexes.empty()) {
208*e5eeaa8eSAndroid Build Coastguard Worker // 1. set original_path
209*e5eeaa8eSAndroid Build Coastguard Worker const std::string info_list_file = apex_root + "/apex-info-list.xml";
210*e5eeaa8eSAndroid Build Coastguard Worker auto info_list =
211*e5eeaa8eSAndroid Build Coastguard Worker com::android::apex::readApexInfoList(info_list_file.c_str());
212*e5eeaa8eSAndroid Build Coastguard Worker if (info_list.has_value()) {
213*e5eeaa8eSAndroid Build Coastguard Worker for (const auto& info : info_list->getApexInfo()) {
214*e5eeaa8eSAndroid Build Coastguard Worker // skip inactive apexes
215*e5eeaa8eSAndroid Build Coastguard Worker if (!info.getIsActive()) {
216*e5eeaa8eSAndroid Build Coastguard Worker continue;
217*e5eeaa8eSAndroid Build Coastguard Worker }
218*e5eeaa8eSAndroid Build Coastguard Worker // skip "sharedlibs" apexes
219*e5eeaa8eSAndroid Build Coastguard Worker if (info.getProvideSharedApexLibs()) {
220*e5eeaa8eSAndroid Build Coastguard Worker continue;
221*e5eeaa8eSAndroid Build Coastguard Worker }
222*e5eeaa8eSAndroid Build Coastguard Worker apexes[info.getModuleName()].partition = std::move(info.getPartition());
223*e5eeaa8eSAndroid Build Coastguard Worker }
224*e5eeaa8eSAndroid Build Coastguard Worker } else {
225*e5eeaa8eSAndroid Build Coastguard Worker return ErrnoError() << "Can't read " << info_list_file;
226*e5eeaa8eSAndroid Build Coastguard Worker }
227*e5eeaa8eSAndroid Build Coastguard Worker
228*e5eeaa8eSAndroid Build Coastguard Worker // 2. set public_libs
229*e5eeaa8eSAndroid Build Coastguard Worker auto system_public_libs =
230*e5eeaa8eSAndroid Build Coastguard Worker ReadPublicLibrariesOpt(root + "/system/etc/public.libraries.txt");
231*e5eeaa8eSAndroid Build Coastguard Worker if (!system_public_libs.ok()) return system_public_libs.error();
232*e5eeaa8eSAndroid Build Coastguard Worker
233*e5eeaa8eSAndroid Build Coastguard Worker auto vendor_public_libs =
234*e5eeaa8eSAndroid Build Coastguard Worker ReadPublicLibrariesOpt(root + "/vendor/etc/public.libraries.txt");
235*e5eeaa8eSAndroid Build Coastguard Worker if (!vendor_public_libs.ok()) return vendor_public_libs.error();
236*e5eeaa8eSAndroid Build Coastguard Worker
237*e5eeaa8eSAndroid Build Coastguard Worker for (auto& [name, apex] : apexes) {
238*e5eeaa8eSAndroid Build Coastguard Worker if (apex.InSystem()) {
239*e5eeaa8eSAndroid Build Coastguard Worker apex.public_libs = Intersect(apex.provide_libs, *system_public_libs);
240*e5eeaa8eSAndroid Build Coastguard Worker } else if (apex.InVendor()) {
241*e5eeaa8eSAndroid Build Coastguard Worker apex.public_libs = Intersect(apex.provide_libs, *vendor_public_libs);
242*e5eeaa8eSAndroid Build Coastguard Worker }
243*e5eeaa8eSAndroid Build Coastguard Worker }
244*e5eeaa8eSAndroid Build Coastguard Worker }
245*e5eeaa8eSAndroid Build Coastguard Worker
246*e5eeaa8eSAndroid Build Coastguard Worker return apexes;
247*e5eeaa8eSAndroid Build Coastguard Worker }
248*e5eeaa8eSAndroid Build Coastguard Worker
InSystem() const249*e5eeaa8eSAndroid Build Coastguard Worker bool ApexInfo::InSystem() const {
250*e5eeaa8eSAndroid Build Coastguard Worker // /system partition
251*e5eeaa8eSAndroid Build Coastguard Worker if (partition.compare("SYSTEM") == 0) {
252*e5eeaa8eSAndroid Build Coastguard Worker return true;
253*e5eeaa8eSAndroid Build Coastguard Worker }
254*e5eeaa8eSAndroid Build Coastguard Worker // /system_ext partition
255*e5eeaa8eSAndroid Build Coastguard Worker if (partition.compare("SYSTEM_EXT") == 0) {
256*e5eeaa8eSAndroid Build Coastguard Worker return true;
257*e5eeaa8eSAndroid Build Coastguard Worker }
258*e5eeaa8eSAndroid Build Coastguard Worker // /product partition if it's not separated from "system"
259*e5eeaa8eSAndroid Build Coastguard Worker if (!IsTreblelizedDevice() && partition.compare("PRODUCT") == 0) {
260*e5eeaa8eSAndroid Build Coastguard Worker return true;
261*e5eeaa8eSAndroid Build Coastguard Worker }
262*e5eeaa8eSAndroid Build Coastguard Worker return false;
263*e5eeaa8eSAndroid Build Coastguard Worker }
264*e5eeaa8eSAndroid Build Coastguard Worker
InProduct() const265*e5eeaa8eSAndroid Build Coastguard Worker bool ApexInfo::InProduct() const {
266*e5eeaa8eSAndroid Build Coastguard Worker // /product partition if it's separated from "system"
267*e5eeaa8eSAndroid Build Coastguard Worker if (IsTreblelizedDevice()) {
268*e5eeaa8eSAndroid Build Coastguard Worker if (partition.compare("PRODUCT") == 0) {
269*e5eeaa8eSAndroid Build Coastguard Worker return true;
270*e5eeaa8eSAndroid Build Coastguard Worker }
271*e5eeaa8eSAndroid Build Coastguard Worker }
272*e5eeaa8eSAndroid Build Coastguard Worker return false;
273*e5eeaa8eSAndroid Build Coastguard Worker }
274*e5eeaa8eSAndroid Build Coastguard Worker
InVendor() const275*e5eeaa8eSAndroid Build Coastguard Worker bool ApexInfo::InVendor() const {
276*e5eeaa8eSAndroid Build Coastguard Worker // /vendor and /odm partition
277*e5eeaa8eSAndroid Build Coastguard Worker if (partition.compare("VENDOR") == 0 || partition.compare("ODM") == 0) {
278*e5eeaa8eSAndroid Build Coastguard Worker return true;
279*e5eeaa8eSAndroid Build Coastguard Worker }
280*e5eeaa8eSAndroid Build Coastguard Worker return false;
281*e5eeaa8eSAndroid Build Coastguard Worker }
282*e5eeaa8eSAndroid Build Coastguard Worker
283*e5eeaa8eSAndroid Build Coastguard Worker } // namespace modules
284*e5eeaa8eSAndroid Build Coastguard Worker } // namespace linkerconfig
285*e5eeaa8eSAndroid Build Coastguard Worker } // namespace android
286