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
66c59326ec5bcae86051571a0824e39e01fc2c4053Steven MorelandAST* Coordinator::parse(const FQName& fqName, std::set<AST*>* parsedASTs,
67c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland                        Enforce enforcement) const {
6868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
6968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
70d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    auto it = mCache.find(fqName);
71d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    if (it != mCache.end()) {
72d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland        AST *ast = (*it).second;
735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
7439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        if (ast != nullptr && parsedASTs != nullptr) {
7539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber            parsedASTs->insert(ast);
7639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        }
7739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
805345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
8168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
82d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = nullptr;
8339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
8439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    AST *typesAST = nullptr;
8568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
8668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
8768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
88fece6ecab34d69d38f57419d2500017a7136083eYifan Hong        FQName typesName = fqName.getTypesForPackage();
89a407b7d4ce6cfa8385e30b8a7e7e06e92a1a3681Steven Moreland        // Do not enforce on imports. Do not add imports' imports to this AST.
90a407b7d4ce6cfa8385e30b8a7e7e06e92a1a3681Steven Moreland        typesAST = parse(typesName, nullptr, Enforce::NONE);
9168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
9268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
9368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
9468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
95b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    std::string path = getAbsolutePackagePath(fqName);
96dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
9768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
9868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
995345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1000d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    AST *ast = new AST(this, path);
10139fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
10239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (typesAST != NULL) {
10339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // If types.hal for this AST's package existed, make it's defined
10439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        // types available to the (about to be parsed) AST right away.
10539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast->addImportedAST(typesAST);
10639fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    }
10739fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
1080d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber    status_t err = parseFile(ast);
10968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
11068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
11168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
11239fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
1135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
11439fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
11568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
11668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
117a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
118a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
11970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber        fprintf(stderr,
12070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                "ERROR: File at '%s' does not match expected package and/or "
1210d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                "version.\n",
12270a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                path.c_str());
123a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
124a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
125a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
12619f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland        if (ast->isInterface()) {
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(),
13219f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland                        ast->getInterface()->localName().c_str());
133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
134a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
13519f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland            } else if (ast->getInterface()->localName() != 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
175c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    // For each .hal file that hidl-gen parses, the whole package will be checked.
176c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    err = enforceRestrictionsOnPackage(fqName, enforcement);
177c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    if (err != OK) {
178c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        mCache[fqName] = nullptr;
179c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        delete ast;
180c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        ast = nullptr;
181c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        return nullptr;
18278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
18378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
1845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
187dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
188dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1895345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
191dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
192dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
19962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    auto ret = mPackageRoots.end();
200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
20162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        if (!fqName.inPackage(*it)) {
20262709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            continue;
203dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20562709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        CHECK(ret == mPackageRoots.end())
20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << "Multiple package roots found for " << fqName.string()
20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << " (" << *it << " and " << *ret << ")";
20862709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        ret = it;
210dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
21162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    CHECK(ret != mPackageRoots.end())
212401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber        << "Unable to find package root for " << fqName.string();
213dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
21462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    return ret;
215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
216dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
217b90d327e82303b3e7abaa5fca6a83e168598a162Steven Morelandstd::string Coordinator::getAbsolutePackagePath(const FQName& fqName) const {
218b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    const std::string packagePath = getPackagePath(fqName);
219b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland
220b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    if (StringHelper::StartsWith(packagePath, "/") || mRootPath.empty()) {
221b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland        return packagePath;
222b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    }
223b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland
224b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    return StringHelper::RTrim(mRootPath, "/") + "/" + packagePath;
225b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland}
226b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland
227dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
228dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
229dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
230dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
231dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
232dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
2335bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
2345bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
2355bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
2365bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
2375bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
2385bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
239c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const {
240c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong    return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName);
241c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong}
242c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong
243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
24497288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong        const FQName &fqName, bool relative, bool sanitized) const {
245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
250dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
251dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
252dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
254dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
255dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
256dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
257dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
258dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
259dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
260dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
261dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
263881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
264881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
265dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
266881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
2725345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
2755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
2775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
2785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
28097288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong    packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version());
2815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
2845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2906cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
291b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland    const std::string packagePath = getAbsolutePackagePath(package);
292d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
296028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland        fprintf(stderr,
297028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                "ERROR: Could not open package path %s for package %s:\n%s\n",
298028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                getPackagePath(package).c_str(),
299028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                package.string().c_str(),
300028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                packagePath.c_str());
301d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
3076cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
3086cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
3096cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
313e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
317e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
318d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
319d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
320e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
321e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
322d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
323d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3255e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev    std::sort(fileNames->begin(), fileNames->end(),
3265e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              [](const std::string& lhs, const std::string& rhs) -> bool {
3275e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (lhs == "types") {
3285e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return true;
3295e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3305e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (rhs == "types") {
3315e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return false;
3325e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3335e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  return lhs < rhs;
3345e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              });
3355e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev
336e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
337e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
338e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
339aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector(
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
35390ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                package.package() + package.atVersion() + "::" + fileName);
354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
36190ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                << package.atVersion();
362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
368d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
369d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
370d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
371d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
372d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
373d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
374d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
375d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
376d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
377d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
378d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
379d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
380d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
381d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
382d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
383d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
384c59326ec5bcae86051571a0824e39e01fc2c4053Steven Morelandstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName& fqName,
385c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland                                                   Enforce enforcement) const {
386c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    CHECK(enforcement == Enforce::FULL || enforcement == Enforce::NO_HASH ||
387c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland          enforcement == Enforce::NONE);
38878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
38978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // need fqName to be something like android.hardware.foo@1.0.
39078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // name and valueName is ignored.
39178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (fqName.package().empty() || fqName.version().empty()) {
39278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string()
39378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": package or version is missing.";
39478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return BAD_VALUE;
39578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
396c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland
397c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    if (enforcement == Enforce::NONE) {
398c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        return OK;
399c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    }
400c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland
40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName package = fqName.getPackageAndVersion();
40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // look up cache.
40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) {
40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // enforce all rules.
408218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err;
409218625af26dea71d188361598c1f8c273716830eSteven Moreland
410218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceMinorVersionUprevs(package);
411218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
412218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
413218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
414218625af26dea71d188361598c1f8c273716830eSteven Moreland
415c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland    if (enforcement != Enforce::NO_HASH) {
416c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        err = enforceHashes(package);
417c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        if (err != OK) {
418c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland            return err;
419c59326ec5bcae86051571a0824e39e01fc2c4053Steven Moreland        }
42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // cache it so that it won't need to be enforced again.
42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    mPackagesEnforced.insert(package);
42478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    return OK;
42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
42728b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceMinorVersionUprevs(const FQName &currentPackage) const {
42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if(!currentPackage.hasVersion()) {
42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": missing version.";
43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (currentPackage.getPackageMinorVersion() == 0) {
43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK; // ignore for @x.0
43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    bool hasPrevPackage = false;
439ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland    FQName prevPackage = currentPackage;
440ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland    while (prevPackage.getPackageMinorVersion() > 0) {
441ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        prevPackage = prevPackage.downRev();
442b90d327e82303b3e7abaa5fca6a83e168598a162Steven Moreland        if (existdir(getAbsolutePackagePath(prevPackage).c_str())) {
44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            hasPrevPackage = true;
44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            break;
44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (!hasPrevPackage) {
44878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // no @x.z, where z < y, exist.
44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
452ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland    if (prevPackage != currentPackage.downRev()) {
45378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
454ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                   << ": Found package " << prevPackage.string() << " but missing "
45578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << currentPackage.downRev().string() << "; you cannot skip a minor version.";
45678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
45778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
45878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
45978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    status_t err;
46078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    std::vector<FQName> packageInterfaces;
46178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
46278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
46378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
46478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
46578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
466fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    bool extendedInterface = false;
46778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    for (const FQName &currentFQName : packageInterfaces) {
46878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentFQName.name() == "types") {
46978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue; // ignore types.hal
47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
471ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        const Interface *iface = nullptr;
47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        AST *currentAST = parse(currentFQName);
47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentAST != nullptr) {
47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            iface = currentAST->getInterface();
47678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
47778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface == nullptr) {
478fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (currentAST == nullptr) {
479fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
480fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because it could not be found or parsed"
481fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " or " << currentPackage.string()
482fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " doesn't pass all requirements.";
483fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            } else {
484fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
485fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because the file might contain more than one interface.";
486fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            }
48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
48878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
48978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType() == nullptr) {
491ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland            CHECK(iface->isIBase());
49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
49378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
494ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
495ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        // Assume that currentFQName == android.hardware.foo@2.2::IFoo.
496ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        FQName lastFQName(prevPackage.package(), prevPackage.version(),
497ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                currentFQName.name());
498ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        AST *lastAST = parse(lastFQName);
499ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
500ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        for (; lastFQName.getPackageMinorVersion() > 0 &&
501ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland               (lastAST == nullptr || lastAST->getInterface() == nullptr)
502ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland             ; lastFQName = lastFQName.downRev(), lastAST = parse(lastFQName)) {
503ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland            // nothing
504ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        }
505ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
506ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        // Then lastFQName == android.hardware.foo@2.1::IFoo or
507ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        //      lastFQName == android.hardware.foo@2.0::IFoo if 2.1 doesn't exist.
508ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
509ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        bool lastFQNameExists = lastAST != nullptr && lastAST->getInterface() != nullptr;
510ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
511ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        if (iface->superType()->fqName() != lastFQName && lastFQNameExists) {
512ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland            LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
513ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                       << ": " << iface->fqName().string() << " extends "
514ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                       << iface->superType()->fqName().string()
515ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                       << ", which is not allowed. It must extend " << lastFQName.string();
516ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland            return UNKNOWN_ERROR;
517ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        }
518ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland
519ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        // at least one interface must extend the previous version
520ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland        if (lastFQName.getPackageAndVersion() == prevPackage.getPackageAndVersion()) {
521ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland            extendedInterface = true;
52278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
52378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
52478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes.";
52578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
52678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
527fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    if (!extendedInterface) {
528fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // No interface extends the interface with the same name in @x.(y-1).
529fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. "
530fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "Requires at least one interface to extend an interface with the same name "
531ad79f56baa069841bdcc1e63d2a62879ee7a5761Steven Moreland                   << "from " << prevPackage.string() << ".";
532fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        return UNKNOWN_ERROR;
533fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    }
534fe07bffd9381605a6f96848a71489a4987363277Yifan Hong
535fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    return OK;
53678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
53778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
53828b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceHashes(const FQName &currentPackage) const {
539218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err = OK;
540218625af26dea71d188361598c1f8c273716830eSteven Moreland    std::vector<FQName> packageInterfaces;
541218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
542218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
543218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
544218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
545218625af26dea71d188361598c1f8c273716830eSteven Moreland
546218625af26dea71d188361598c1f8c273716830eSteven Moreland    for (const FQName &currentFQName : packageInterfaces) {
547218625af26dea71d188361598c1f8c273716830eSteven Moreland        AST *ast = parse(currentFQName);
548218625af26dea71d188361598c1f8c273716830eSteven Moreland
549218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (ast == nullptr) {
550218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
551218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
552218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
553218625af26dea71d188361598c1f8c273716830eSteven Moreland
5545bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt";
555218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string error;
5565bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error);
557218625af26dea71d188361598c1f8c273716830eSteven Moreland
558218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (error.size() > 0) {
559218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << error;
560218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
561218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
562218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
563218625af26dea71d188361598c1f8c273716830eSteven Moreland
564218625af26dea71d188361598c1f8c273716830eSteven Moreland        // hash not define, interface not frozen
565218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (frozen.size() == 0) {
566218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
567218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
568218625af26dea71d188361598c1f8c273716830eSteven Moreland
569218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string currentHash = Hash::getHash(ast->getFilename()).hexString();
570218625af26dea71d188361598c1f8c273716830eSteven Moreland
571218625af26dea71d188361598c1f8c273716830eSteven Moreland        if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) {
572218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << currentFQName.string() << " has hash " << currentHash
573218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << " which does not match hash on record. This interface has "
574218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << "been frozen. Do not change it!";
575218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
576218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
577218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
578218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
579218625af26dea71d188361598c1f8c273716830eSteven Moreland
580218625af26dea71d188361598c1f8c273716830eSteven Moreland    return err;
581218625af26dea71d188361598c1f8c273716830eSteven Moreland}
582218625af26dea71d188361598c1f8c273716830eSteven Moreland
583d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
584d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
585d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
586d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
587d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
588d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
589d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
590d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
591d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
592d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
593d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
594d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
595d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
596d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
597d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
598d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
599d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
600d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
601d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
602d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
603d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
604d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
605d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
606d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
607d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
608d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
609d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
610d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
6115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
6125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
613