Coordinator.cpp revision 28b9b537a4941ac9e4ef2e25e64e3ffc4b833676
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
5925c8166fa1e40db71497bf9cbc67d313e5f808edSteven Morelandvoid Coordinator::addDefaultPackagePath(const std::string& root, const std::string& path) {
6025c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland    if (std::find(mPackageRoots.begin(), mPackageRoots.end(), root) == mPackageRoots.end()) {
6125c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland        mPackageRoots.push_back(root);
6225c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland        mPackageRootPaths.push_back(path);
6325c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland    }
6425c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland}
6525c8166fa1e40db71497bf9cbc67d313e5f808edSteven Moreland
6628b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven MorelandAST *Coordinator::parse(const FQName &fqName, std::set<AST *> *parsedASTs, bool enforce) const {
6768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
6868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
69d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    auto it = mCache.find(fqName);
70d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    if (it != mCache.end()) {
71d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland        AST *ast = (*it).second;
725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
7339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        if (ast != nullptr && parsedASTs != nullptr) {
7439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber            parsedASTs->insert(ast);
7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        }
7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
8068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
81d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = nullptr;
8239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
8339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    AST *typesAST = nullptr;
8468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
87fece6ecab34d69d38f57419d2500017a7136083eYifan Hong        FQName typesName = fqName.getTypesForPackage();
88f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        // Do not enforce on imports.
89f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        typesAST = parse(typesName, parsedASTs, false /* enforce */);
9068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
9168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
9268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
9368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
94f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland    std::string path = mRootPath + getPackagePath(fqName);
95dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
9668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
9768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
985345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
990d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    AST *ast = new AST(this, path);
10039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
10139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (typesAST != NULL) {
10239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // If types.hal for this AST's package existed, make it's defined
10339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // types available to the (about to be parsed) AST right away.
10439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast->addImportedAST(typesAST);
10539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    }
10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
1070d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    status_t err = parseFile(ast);
10868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
11139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
1125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
11339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
11468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
11568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
116a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
11870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber        fprintf(stderr,
11970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                "ERROR: File at '%s' does not match expected package and/or "
1200d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                "version.\n",
12170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                path.c_str());
122a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
123a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
124a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
125a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        std::string ifaceName;
126a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        if (ast->isInterface(&ifaceName)) {
127a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
12870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
12970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' declares an interface '%s' "
1300d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "instead of the expected types common to the package.\n",
13170a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
13270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        ifaceName.c_str());
133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
134a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
135a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            } else if (ifaceName != fqName.name()) {
13670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
13770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' does not declare interface type "
1380d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "'%s'.\n",
13970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
14070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        fqName.name().c_str());
141a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
142a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
143a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
144a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
14570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber            fprintf(stderr,
14670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    "ERROR: File at '%s' declares types rather than the "
1470d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                    "expected interface type '%s'.\n",
14870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    path.c_str(),
14970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    fqName.name().c_str());
150a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
151a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber        } else if (ast->containsInterfaces()) {
1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            fprintf(stderr,
1547c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "ERROR: types.hal file at '%s' declares at least one "
1557c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "interface type.\n",
1567c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    path.c_str());
1577c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber
1587c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            err = UNKNOWN_ERROR;
159a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
161a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
163a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
16439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
165a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
167a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
168a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (parsedASTs != nullptr) { parsedASTs->insert(ast); }
17039fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
171fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // put it into the cache now, so that enforceRestrictionsOnPackage can
172fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // parse fqName.
173d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = ast;
1745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
175f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong    if (enforce) {
176f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        // For each .hal file that hidl-gen parses, the whole package will be checked.
177f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        err = enforceRestrictionsOnPackage(fqName);
178f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        if (err != OK) {
179f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            mCache[fqName] = nullptr;
180f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            delete ast;
181f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            ast = nullptr;
182f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            return nullptr;
183f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        }
18478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
18578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1885345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
190dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1925345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1935345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
199dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
201dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
20262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    auto ret = mPackageRoots.end();
203dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        if (!fqName.inPackage(*it)) {
20562709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            continue;
206dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20862709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        CHECK(ret == mPackageRoots.end())
20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << "Multiple package roots found for " << fqName.string()
21062709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << " (" << *it << " and " << *ret << ")";
21162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
21262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        ret = it;
213dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
21462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    CHECK(ret != mPackageRoots.end())
215401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber        << "Unable to find package root for " << fqName.string();
216dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
21762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    return ret;
218dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
219dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
220dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
221dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
222dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
223dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
224dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
225dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
2265bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
2275bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
2285bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
2295bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
2305bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
2315bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
232c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const {
233c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong    return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName);
234c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong}
235c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong
236dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
23797288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong        const FQName &fqName, bool relative, bool sanitized) const {
238dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
239dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
240dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
241dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
242dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
244dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
250dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
251dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
252dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
254dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
2555345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
256881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
257881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
258dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
259881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
2605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2615345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
2635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
2645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
2655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
2665345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
2685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
27397288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong    packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version());
2745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
2775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
279d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2836cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
284f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland    const std::string packagePath = mRootPath + getPackagePath(package);
285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
289028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland        fprintf(stderr,
290028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                "ERROR: Could not open package path %s for package %s:\n%s\n",
291028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                getPackagePath(package).c_str(),
292028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                package.string().c_str(),
293028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                packagePath.c_str());
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
3006cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
3016cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
3026cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
306e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
309d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
310e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
313e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
314e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
317d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3185e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev    std::sort(fileNames->begin(), fileNames->end(),
3195e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              [](const std::string& lhs, const std::string& rhs) -> bool {
3205e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (lhs == "types") {
3215e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return true;
3225e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3235e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (rhs == "types") {
3245e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return false;
3255e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3265e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  return lhs < rhs;
3275e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              });
3285e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev
329e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
330e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
331e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
332aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector(
333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
34690ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                package.package() + package.atVersion() + "::" + fileName);
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
353d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
35490ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                << package.atVersion();
355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
361d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
368d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
369d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
370d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
371d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
372d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
373d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
374d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
375d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
376d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
37778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
37828b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName &fqName) const {
37978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // need fqName to be something like android.hardware.foo@1.0.
38078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // name and valueName is ignored.
38178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (fqName.package().empty() || fqName.version().empty()) {
38278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string()
38378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": package or version is missing.";
38478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return BAD_VALUE;
38578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
38678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName package = fqName.getPackageAndVersion();
38778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // look up cache.
38878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) {
38978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
39078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
39178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
39278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // enforce all rules.
393218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err;
394218625af26dea71d188361598c1f8c273716830eSteven Moreland
395218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceMinorVersionUprevs(package);
396218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
397218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
398218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
399218625af26dea71d188361598c1f8c273716830eSteven Moreland
400218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceHashes(package);
40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // cache it so that it won't need to be enforced again.
40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    mPackagesEnforced.insert(package);
40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    return OK;
40878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
40978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
41028b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceMinorVersionUprevs(const FQName &currentPackage) const {
41178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if(!currentPackage.hasVersion()) {
41278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
41378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": missing version.";
41478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
41578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
41678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
41778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (currentPackage.getPackageMinorVersion() == 0) {
41878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK; // ignore for @x.0
41978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    bool hasPrevPackage = false;
42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName prevPacakge = currentPackage;
42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    while (prevPacakge.getPackageMinorVersion() > 0) {
42478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        prevPacakge = prevPacakge.downRev();
425f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland        if (existdir((mRootPath + getPackagePath(prevPacakge)).c_str())) {
42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            hasPrevPackage = true;
42778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            break;
42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (!hasPrevPackage) {
43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // no @x.z, where z < y, exist.
43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (prevPacakge != currentPackage.downRev()) {
43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": Found package " << prevPacakge.string() << " but missing "
43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << currentPackage.downRev().string() << "; you cannot skip a minor version.";
43978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
44078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
44178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
44278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    status_t err;
44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    std::vector<FQName> packageInterfaces;
44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
44878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
449fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    bool extendedInterface = false;
45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    for (const FQName &currentFQName : packageInterfaces) {
45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentFQName.name() == "types") {
45278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue; // ignore types.hal
45378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
45478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Assume that currentFQName == android.hardware.foo@2.2::IFoo.
45578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Then prevFQName == android.hardware.foo@2.1::IFoo.
45678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        const Interface *iface = nullptr;
45778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        AST *currentAST = parse(currentFQName);
45878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentAST != nullptr) {
45978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            iface = currentAST->getInterface();
46078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
46178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface == nullptr) {
462fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (currentAST == nullptr) {
463fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
464fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because it could not be found or parsed"
465fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " or " << currentPackage.string()
466fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " doesn't pass all requirements.";
467fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            } else {
468fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
469fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because the file might contain more than one interface.";
470fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            }
47178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // android.hardware.foo@2.2::IFoo exists. Now make sure
47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // @2.2::IFoo extends @2.1::IFoo. If any interface IFoo in @2.2
47678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // ensures this, @2.2 passes the enforcement.
47778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        FQName prevFQName(prevPacakge.package(), prevPacakge.version(),
47878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                currentFQName.name());
47978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType() == nullptr) {
48078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend anything. (This is probably IBase.)
48178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
48278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
48378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType()->fqName() != prevFQName) {
48478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend @2.1::IFoo.
485fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (iface->superType()->fqName().getPackageAndVersion() ==
486fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                    prevPacakge.getPackageAndVersion()) {
48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
48878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << ": " << iface->fqName().string() << " extends "
48978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << iface->superType()->fqName().string() << ", which is not allowed.";
49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                return UNKNOWN_ERROR;
49178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            }
49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo extends something from a package with a different package name.
49378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // Check the next interface.
49478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
49578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
49678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
497fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // @2.2::IFoo passes. Check next interface.
498fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        extendedInterface = true;
49978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes.";
50078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
50178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
502fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    if (!extendedInterface) {
503fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // No interface extends the interface with the same name in @x.(y-1).
504fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. "
505fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "Requires at least one interface to extend an interface with the same name "
506fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "from " << prevPacakge.string() << ".";
507fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        return UNKNOWN_ERROR;
508fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    }
509fe07bffd9381605a6f96848a71489a4987363277Yifan Hong
510fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    return OK;
51178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
51278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
51328b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceHashes(const FQName &currentPackage) const {
514218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err = OK;
515218625af26dea71d188361598c1f8c273716830eSteven Moreland    std::vector<FQName> packageInterfaces;
516218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
517218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
518218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
519218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
520218625af26dea71d188361598c1f8c273716830eSteven Moreland
521218625af26dea71d188361598c1f8c273716830eSteven Moreland    for (const FQName &currentFQName : packageInterfaces) {
522218625af26dea71d188361598c1f8c273716830eSteven Moreland        AST *ast = parse(currentFQName);
523218625af26dea71d188361598c1f8c273716830eSteven Moreland
524218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (ast == nullptr) {
525218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
526218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
527218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
528218625af26dea71d188361598c1f8c273716830eSteven Moreland
5295bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt";
530218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string error;
5315bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error);
532218625af26dea71d188361598c1f8c273716830eSteven Moreland
533218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (error.size() > 0) {
534218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << error;
535218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
536218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
537218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
538218625af26dea71d188361598c1f8c273716830eSteven Moreland
539218625af26dea71d188361598c1f8c273716830eSteven Moreland        // hash not define, interface not frozen
540218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (frozen.size() == 0) {
541218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
542218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
543218625af26dea71d188361598c1f8c273716830eSteven Moreland
544218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string currentHash = Hash::getHash(ast->getFilename()).hexString();
545218625af26dea71d188361598c1f8c273716830eSteven Moreland
546218625af26dea71d188361598c1f8c273716830eSteven Moreland        if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) {
547218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << currentFQName.string() << " has hash " << currentHash
548218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << " which does not match hash on record. This interface has "
549218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << "been frozen. Do not change it!";
550218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
551218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
552218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
553218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
554218625af26dea71d188361598c1f8c273716830eSteven Moreland
555218625af26dea71d188361598c1f8c273716830eSteven Moreland    return err;
556218625af26dea71d188361598c1f8c273716830eSteven Moreland}
557218625af26dea71d188361598c1f8c273716830eSteven Moreland
558d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
559d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
560d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
561d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
562d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
563d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
564d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
565d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
566d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
567d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
568d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
569d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
570d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
571d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
572d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
573d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
574d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
575d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
576d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
577d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
578d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
579d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
580d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
581d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
582d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
583d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
584d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
585d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
5865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
5875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
588