Coordinator.cpp revision f7fa068fe10f7ba5df8c4352686e906486ebec0f
11aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber/*
21aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Copyright (C) 2016 The Android Open Source Project
31aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
41aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
51aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * you may not use this file except in compliance with the License.
61aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * You may obtain a copy of the License at
71aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
81aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
91aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber *
101aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * Unless required by applicable law or agreed to in writing, software
111aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
121aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * See the License for the specific language governing permissions and
141aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber * limitations under the License.
151aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber */
161aec397b1fdea7db4120dbe55b6995bb2a9d9138Andreas Huber
175345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "Coordinator.h"
185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <dirent.h>
2078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <sys/stat.h>
215345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
225e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev#include <algorithm>
2378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include <iterator>
2478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h>
265bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland#include <hidl-hash/Hash.h>
275715fedbd05231bf845e3a120c83b931b7f53aa3Steven Moreland#include <hidl-util/StringHelper.h>
2878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
2978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include "AST.h"
3078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong#include "Interface.h"
315345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
320d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huberextern android::status_t parseFile(android::AST *ast);
335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
3478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatic bool existdir(const char *name) {
3578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    DIR *dir = opendir(name);
3678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (dir == NULL) {
3778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return false;
3878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
3978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    closedir(dir);
4078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    return true;
4178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
4278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
435345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android {
445345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
45dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::Coordinator(
46dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const std::vector<std::string> &packageRootPaths,
47f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland        const std::vector<std::string> &packageRoots,
48f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland        const std::string &rootPath)
49dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    : mPackageRootPaths(packageRootPaths),
50f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland      mPackageRoots(packageRoots),
51f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland      mRootPath(rootPath) {
52dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
53dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber}
54dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber
55dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::~Coordinator() {
56dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
57dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
585345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
59f619fc7bef5a4af1c196e125d70293d4af85e396Yifan HongAST *Coordinator::parse(const FQName &fqName, std::set<AST *> *parsedASTs, bool enforce) {
6068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
6168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
62d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    auto it = mCache.find(fqName);
63d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    if (it != mCache.end()) {
64d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland        AST *ast = (*it).second;
655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
6639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        if (ast != nullptr && parsedASTs != nullptr) {
6739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber            parsedASTs->insert(ast);
6839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        }
6939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
7368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
74d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = nullptr;
7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    AST *typesAST = nullptr;
7768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
7868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
7968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
80fece6ecab34d69d38f57419d2500017a7136083eYifan Hong        FQName typesName = fqName.getTypesForPackage();
81f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        // Do not enforce on imports.
82f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        typesAST = parse(typesName, parsedASTs, false /* enforce */);
8368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
8468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
87f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland    std::string path = mRootPath + getPackagePath(fqName);
88dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
8968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
9068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
920d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    AST *ast = new AST(this, path);
9339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
9439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (typesAST != NULL) {
9539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // If types.hal for this AST's package existed, make it's defined
9639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // types available to the (about to be parsed) AST right away.
9739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast->addImportedAST(typesAST);
9839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    }
9939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
1000d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    status_t err = parseFile(ast);
10168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
10268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
1036e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        // LOG(ERROR) << "parsing '" << path << "' FAILED.";
1046e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
10568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
1075345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
10839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
111a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
112a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
11370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber        fprintf(stderr,
11470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                "ERROR: File at '%s' does not match expected package and/or "
1150d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                "version.\n",
11670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                path.c_str());
117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
118a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
119a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
120a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        std::string ifaceName;
121a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        if (ast->isInterface(&ifaceName)) {
122a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
12370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
12470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' declares an interface '%s' "
1250d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "instead of the expected types common to the package.\n",
12670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
12770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        ifaceName.c_str());
128a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
129a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
130a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            } else if (ifaceName != fqName.name()) {
13170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
13270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' does not declare interface type "
1330d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "'%s'.\n",
13470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
13570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        fqName.name().c_str());
136a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
137a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
138a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
139a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
14070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber            fprintf(stderr,
14170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    "ERROR: File at '%s' declares types rather than the "
1420d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                    "expected interface type '%s'.\n",
14370a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    path.c_str(),
14470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    fqName.name().c_str());
145a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
146a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
1477c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber        } else if (ast->containsInterfaces()) {
1487c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            fprintf(stderr,
1497c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "ERROR: types.hal file at '%s' declares at least one "
1507c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "interface type.\n",
1517c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    path.c_str());
1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber
1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            err = UNKNOWN_ERROR;
154a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
155a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
156a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
157a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
158a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
15939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
163a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (parsedASTs != nullptr) { parsedASTs->insert(ast); }
16539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
166fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // put it into the cache now, so that enforceRestrictionsOnPackage can
167fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // parse fqName.
168d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = ast;
1695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
170f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong    if (enforce) {
171f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        // For each .hal file that hidl-gen parses, the whole package will be checked.
172f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        err = enforceRestrictionsOnPackage(fqName);
173f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        if (err != OK) {
174f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            mCache[fqName] = nullptr;
175f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            delete ast;
176f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            ast = nullptr;
177f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            return nullptr;
178f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        }
17978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
18078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
1815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
184dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
185dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1885345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
190dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
191dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
192dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
19762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    auto ret = mPackageRoots.end();
198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
19962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        if (!fqName.inPackage(*it)) {
20062709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            continue;
201dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
20262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        CHECK(ret == mPackageRoots.end())
20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << "Multiple package roots found for " << fqName.string()
20562709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << " (" << *it << " and " << *ret << ")";
20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        ret = it;
208dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    CHECK(ret != mPackageRoots.end())
210401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber        << "Unable to find package root for " << fqName.string();
211dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
21262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    return ret;
213dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
214dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
216dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
217dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
218dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
219dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
220dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
2215bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
2225bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
2235bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
2245bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
2255bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
2265bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
227c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const {
228c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong    return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName);
229c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong}
230c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong
231dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
23297288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong        const FQName &fqName, bool relative, bool sanitized) const {
233dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
234dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
235dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
236dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
237dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
238dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
239dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
240dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
241dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
242dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
244dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
2505345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
251881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
252881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
254881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
2555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2565345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
2575345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
2585345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
2595345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
2605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
2615345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
2635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
2655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
2665345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
26897288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong    packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version());
2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
2725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
274d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
275d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
276d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
277d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2786cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
279f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland    const std::string packagePath = mRootPath + getPackagePath(package);
280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
283d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
284261370ae8d57b78b01e4168abcf54d506f946f24Steven Moreland        LOG(ERROR) << "Could not open package path: " << packagePath;
285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
290d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
2916cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
2926cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
2936cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
297e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
300d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
301e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
304e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
305e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3095e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev    std::sort(fileNames->begin(), fileNames->end(),
3105e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              [](const std::string& lhs, const std::string& rhs) -> bool {
3115e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (lhs == "types") {
3125e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return true;
3135e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3145e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (rhs == "types") {
3155e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return false;
3165e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3175e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  return lhs < rhs;
3185e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              });
3195e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev
320e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
321e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
322e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
323aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector(
324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
325d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
326d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
327d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
328d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
329d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
330d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
331d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
33790ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                package.package() + package.atVersion() + "::" + fileName);
338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
34590ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                << package.atVersion();
346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
353d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
361d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
36878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
36978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName &fqName) {
37078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // need fqName to be something like android.hardware.foo@1.0.
37178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // name and valueName is ignored.
37278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (fqName.package().empty() || fqName.version().empty()) {
37378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string()
37478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": package or version is missing.";
37578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return BAD_VALUE;
37678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
37778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName package = fqName.getPackageAndVersion();
37878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // look up cache.
37978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) {
38078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
38178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
38278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
38378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // enforce all rules.
384218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err;
385218625af26dea71d188361598c1f8c273716830eSteven Moreland
386218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceMinorVersionUprevs(package);
387218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
388218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
389218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
390218625af26dea71d188361598c1f8c273716830eSteven Moreland
391218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceHashes(package);
39278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
39378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
39478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
39578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
39678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // cache it so that it won't need to be enforced again.
39778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    mPackagesEnforced.insert(package);
39878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    return OK;
39978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
40078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hongstatus_t Coordinator::enforceMinorVersionUprevs(const FQName &currentPackage) {
40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if(!currentPackage.hasVersion()) {
40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": missing version.";
40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (currentPackage.getPackageMinorVersion() == 0) {
40978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK; // ignore for @x.0
41078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
41178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
41278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    bool hasPrevPackage = false;
41378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName prevPacakge = currentPackage;
41478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    while (prevPacakge.getPackageMinorVersion() > 0) {
41578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        prevPacakge = prevPacakge.downRev();
416f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland        if (existdir((mRootPath + getPackagePath(prevPacakge)).c_str())) {
41778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            hasPrevPackage = true;
41878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            break;
41978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (!hasPrevPackage) {
42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // no @x.z, where z < y, exist.
42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
42478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (prevPacakge != currentPackage.downRev()) {
42778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": Found package " << prevPacakge.string() << " but missing "
42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << currentPackage.downRev().string() << "; you cannot skip a minor version.";
43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    status_t err;
43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    std::vector<FQName> packageInterfaces;
43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
440fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    bool extendedInterface = false;
44178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    for (const FQName &currentFQName : packageInterfaces) {
44278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentFQName.name() == "types") {
44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue; // ignore types.hal
44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Assume that currentFQName == android.hardware.foo@2.2::IFoo.
44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Then prevFQName == android.hardware.foo@2.1::IFoo.
44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        const Interface *iface = nullptr;
44878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        AST *currentAST = parse(currentFQName);
44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentAST != nullptr) {
45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            iface = currentAST->getInterface();
45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
45278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface == nullptr) {
453fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (currentAST == nullptr) {
454fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
455fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because it could not be found or parsed"
456fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " or " << currentPackage.string()
457fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " doesn't pass all requirements.";
458fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            } else {
459fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
460fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because the file might contain more than one interface.";
461fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            }
46278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
46378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
46478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
46578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // android.hardware.foo@2.2::IFoo exists. Now make sure
46678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // @2.2::IFoo extends @2.1::IFoo. If any interface IFoo in @2.2
46778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // ensures this, @2.2 passes the enforcement.
46878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        FQName prevFQName(prevPacakge.package(), prevPacakge.version(),
46978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                currentFQName.name());
47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType() == nullptr) {
47178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend anything. (This is probably IBase.)
47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType()->fqName() != prevFQName) {
47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend @2.1::IFoo.
476fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (iface->superType()->fqName().getPackageAndVersion() ==
477fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                    prevPacakge.getPackageAndVersion()) {
47878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
47978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << ": " << iface->fqName().string() << " extends "
48078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << iface->superType()->fqName().string() << ", which is not allowed.";
48178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                return UNKNOWN_ERROR;
48278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            }
48378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo extends something from a package with a different package name.
48478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // Check the next interface.
48578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
48678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
488fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // @2.2::IFoo passes. Check next interface.
489fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        extendedInterface = true;
49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes.";
49178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
493fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    if (!extendedInterface) {
494fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // No interface extends the interface with the same name in @x.(y-1).
495fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. "
496fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "Requires at least one interface to extend an interface with the same name "
497fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "from " << prevPacakge.string() << ".";
498fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        return UNKNOWN_ERROR;
499fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    }
500fe07bffd9381605a6f96848a71489a4987363277Yifan Hong
501fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    return OK;
50278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
50378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
504218625af26dea71d188361598c1f8c273716830eSteven Morelandstatus_t Coordinator::enforceHashes(const FQName &currentPackage) {
505218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err = OK;
506218625af26dea71d188361598c1f8c273716830eSteven Moreland    std::vector<FQName> packageInterfaces;
507218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
508218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
509218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
510218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
511218625af26dea71d188361598c1f8c273716830eSteven Moreland
512218625af26dea71d188361598c1f8c273716830eSteven Moreland    for (const FQName &currentFQName : packageInterfaces) {
513218625af26dea71d188361598c1f8c273716830eSteven Moreland        AST *ast = parse(currentFQName);
514218625af26dea71d188361598c1f8c273716830eSteven Moreland
515218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (ast == nullptr) {
516218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
517218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
518218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
519218625af26dea71d188361598c1f8c273716830eSteven Moreland
5205bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt";
521218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string error;
5225bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error);
523218625af26dea71d188361598c1f8c273716830eSteven Moreland
524218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (error.size() > 0) {
525218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << error;
526218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
527218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
528218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
529218625af26dea71d188361598c1f8c273716830eSteven Moreland
530218625af26dea71d188361598c1f8c273716830eSteven Moreland        // hash not define, interface not frozen
531218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (frozen.size() == 0) {
532218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
533218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
534218625af26dea71d188361598c1f8c273716830eSteven Moreland
535218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string currentHash = Hash::getHash(ast->getFilename()).hexString();
536218625af26dea71d188361598c1f8c273716830eSteven Moreland
537218625af26dea71d188361598c1f8c273716830eSteven Moreland        if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) {
538218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << currentFQName.string() << " has hash " << currentHash
539218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << " which does not match hash on record. This interface has "
540218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << "been frozen. Do not change it!";
541218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
542218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
543218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
544218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
545218625af26dea71d188361598c1f8c273716830eSteven Moreland
546218625af26dea71d188361598c1f8c273716830eSteven Moreland    return err;
547218625af26dea71d188361598c1f8c273716830eSteven Moreland}
548218625af26dea71d188361598c1f8c273716830eSteven Moreland
549d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
550d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
551d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
552d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
553d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
554d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
555d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
556d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
557d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
558d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
559d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
560d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
561d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
562d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
563d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
564d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
565d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
566d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
567d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
568d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
569d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
570d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
571d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
572d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
573d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
574d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
575d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
576d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
5775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
5785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
579