Coordinator.cpp revision 19f11b53241877c442d31d9dc6b372e294a500d0
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 {
12519f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland        if (ast->isInterface()) {
126a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
12770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
12870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' declares an interface '%s' "
1290d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "instead of the expected types common to the package.\n",
13070a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
13119f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland                        ast->getInterface()->localName().c_str());
132a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
133a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
13419f11b53241877c442d31d9dc6b372e294a500d0Steven Moreland            } else if (ast->getInterface()->localName() != fqName.name()) {
13570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                fprintf(stderr,
13670a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        "ERROR: File at '%s' does not declare interface type "
1370d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                        "'%s'.\n",
13870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        path.c_str(),
13970a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                        fqName.name().c_str());
140a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
141a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
142a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
143a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
14470a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber            fprintf(stderr,
14570a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    "ERROR: File at '%s' declares types rather than the "
1460d0f9a2e0195a8609f1939c35bd8907253b68249Andreas Huber                    "expected interface type '%s'.\n",
14770a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    path.c_str(),
14870a59e1dc3dcf32f791d2dd7966111d4adf32ecaAndreas Huber                    fqName.name().c_str());
149a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
150a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
1517c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber        } else if (ast->containsInterfaces()) {
1527c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            fprintf(stderr,
1537c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "ERROR: types.hal file at '%s' declares at least one "
1547c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    "interface type.\n",
1557c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber                    path.c_str());
1567c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber
1577c5ddfb41a806a7bf71581952d06b637a7670cf7Andreas Huber            err = UNKNOWN_ERROR;
158a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
159a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
160a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
161a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
162a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
16339fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        ast = nullptr;
164a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16539fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber        return nullptr;
166a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
167a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
16839fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber    if (parsedASTs != nullptr) { parsedASTs->insert(ast); }
16939fa71827738f6c1340e4523946fe9bf704eef3aAndreas Huber
170fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // put it into the cache now, so that enforceRestrictionsOnPackage can
171fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    // parse fqName.
172d537ab02e1707597d70665fd8c75ca1ec9f57326Steven Moreland    mCache[fqName] = ast;
1735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
174f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong    if (enforce) {
175f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        // For each .hal file that hidl-gen parses, the whole package will be checked.
176f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        err = enforceRestrictionsOnPackage(fqName);
177f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        if (err != OK) {
178f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            mCache[fqName] = nullptr;
179f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            delete ast;
180f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            ast = nullptr;
181f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong            return nullptr;
182f619fc7bef5a4af1c196e125d70293d4af85e396Yifan Hong        }
18378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
18478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
188dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
189dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1925345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
193dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
194dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
195dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
196dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
197dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
198dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
199dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
200dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
20162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    auto ret = mPackageRoots.end();
202dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
20362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        if (!fqName.inPackage(*it)) {
20462709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            continue;
205dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
20662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
20762709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        CHECK(ret == mPackageRoots.end())
20862709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << "Multiple package roots found for " << fqName.string()
20962709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland            << " (" << *it << " and " << *ret << ")";
21062709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland
21162709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland        ret = it;
212dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
21362709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    CHECK(ret != mPackageRoots.end())
214401cd16db8a421aaf91338024cea9208549ef67eAndreas Huber        << "Unable to find package root for " << fqName.string();
215dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
21662709d73d7f260fae0a475f8d4d30eb3665e8168Steven Moreland    return ret;
217dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
218dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
219dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
220dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
221dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
222dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
223dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
224dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
2255bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
2265bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
2275bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
2285bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
2295bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
2305bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
231c89340422f53046bfe24ff3e529161f9194120f8Yifan Hongstd::string Coordinator::getPackageRootOption(const FQName &fqName) const {
232c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong    return getPackageRoot(fqName) + ":" + getPackageRootPath(fqName);
233c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong}
234c89340422f53046bfe24ff3e529161f9194120f8Yifan Hong
235dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
23697288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong        const FQName &fqName, bool relative, bool sanitized) const {
237dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
238dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
239dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
240dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
241dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
242dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
243dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
244dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
245dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
246dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
247dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
248dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
249dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
250dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
251dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
252dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
253dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
2545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
255881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
256881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
257dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
258881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
2595345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2605345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
2615345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
2625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
2635345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
2645345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
2655345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2665345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
2675345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
2695345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
2705345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2715345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
27297288acdcff66df30cc443c65ddb815e8d0cfeaaYifan Hong    packagePath.append(sanitized ? fqName.sanitizedVersion() : fqName.version());
2735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
2745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
2765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
278d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
279d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2826cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
283f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland    const std::string packagePath = mRootPath + getPackagePath(package);
284d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
288028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland        fprintf(stderr,
289028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                "ERROR: Could not open package path %s for package %s:\n%s\n",
290028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                getPackagePath(package).c_str(),
291028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                package.string().c_str(),
292028d5a3dd54e1351e656d4702fc7ba3541a55d3cSteven Moreland                packagePath.c_str());
293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
2996cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
3006cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
3016cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
305e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
309e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
312e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
313e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3175e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev    std::sort(fileNames->begin(), fileNames->end(),
3185e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              [](const std::string& lhs, const std::string& rhs) -> bool {
3195e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (lhs == "types") {
3205e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return true;
3215e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3225e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  if (rhs == "types") {
3235e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                      return false;
3245e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  }
3255e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev                  return lhs < rhs;
3265e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev              });
3275e8bcfad6dbb7b85fcd75ae64c569fd6efafb5b8Iliyan Malchev
328e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
329e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
330e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
331aa1868371f36507ff8f6337ec0e6bb02b2620981Steven Morelandstatus_t Coordinator::appendPackageInterfacesToVector(
332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
34590ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                package.package() + package.atVersion() + "::" + fileName);
346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
348d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
349d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
350d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
351d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
352d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
35390ea87f36e60a8db0c12d8e7870d45c90c51922dYifan Hong                << package.atVersion();
354d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
355d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
356d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
357d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
358d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
359d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
360d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
361d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
362d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
363d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
364d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
365d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
366d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
367d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
368d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
369d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
370d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
371d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
372d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
373d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
374d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
375d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
37678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
37728b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceRestrictionsOnPackage(const FQName &fqName) const {
37878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // need fqName to be something like android.hardware.foo@1.0.
37978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // name and valueName is ignored.
38078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (fqName.package().empty() || fqName.version().empty()) {
38178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce restrictions on package " << fqName.string()
38278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": package or version is missing.";
38378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return BAD_VALUE;
38478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
38578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName package = fqName.getPackageAndVersion();
38678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // look up cache.
38778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (mPackagesEnforced.find(package) != mPackagesEnforced.end()) {
38878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
38978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
39078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
39178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // enforce all rules.
392218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err;
393218625af26dea71d188361598c1f8c273716830eSteven Moreland
394218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceMinorVersionUprevs(package);
395218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
396218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
397218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
398218625af26dea71d188361598c1f8c273716830eSteven Moreland
399218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = enforceHashes(package);
40078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
40178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
40278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
40378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    // cache it so that it won't need to be enforced again.
40578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    mPackagesEnforced.insert(package);
40678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    return OK;
40778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
40878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
40928b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceMinorVersionUprevs(const FQName &currentPackage) const {
41078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if(!currentPackage.hasVersion()) {
41178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
41278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": missing version.";
41378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
41478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
41578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
41678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (currentPackage.getPackageMinorVersion() == 0) {
41778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK; // ignore for @x.0
41878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
41978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
42078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    bool hasPrevPackage = false;
42178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    FQName prevPacakge = currentPackage;
42278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    while (prevPacakge.getPackageMinorVersion() > 0) {
42378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        prevPacakge = prevPacakge.downRev();
424f7fa068fe10f7ba5df8c4352686e906486ebec0fSteven Moreland        if (existdir((mRootPath + getPackagePath(prevPacakge)).c_str())) {
42578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            hasPrevPackage = true;
42678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            break;
42778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
42878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
42978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (!hasPrevPackage) {
43078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // no @x.z, where z < y, exist.
43178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return OK;
43278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
43378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
43478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (prevPacakge != currentPackage.downRev()) {
43578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
43678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << ": Found package " << prevPacakge.string() << " but missing "
43778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                   << currentPackage.downRev().string() << "; you cannot skip a minor version.";
43878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return UNKNOWN_ERROR;
43978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
44078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
44178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    status_t err;
44278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    std::vector<FQName> packageInterfaces;
44378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
44478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    if (err != OK) {
44578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        return err;
44678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
44778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
448fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    bool extendedInterface = false;
44978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    for (const FQName &currentFQName : packageInterfaces) {
45078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentFQName.name() == "types") {
45178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue; // ignore types.hal
45278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
45378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Assume that currentFQName == android.hardware.foo@2.2::IFoo.
45478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // Then prevFQName == android.hardware.foo@2.1::IFoo.
45578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        const Interface *iface = nullptr;
45678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        AST *currentAST = parse(currentFQName);
45778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (currentAST != nullptr) {
45878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            iface = currentAST->getInterface();
45978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
46078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface == nullptr) {
461fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (currentAST == nullptr) {
462fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
463fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because it could not be found or parsed"
464fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " or " << currentPackage.string()
465fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " doesn't pass all requirements.";
466fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            } else {
467fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                LOG(WARNING) << "Warning: Skipping " << currentFQName.string()
468fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                             << " because the file might contain more than one interface.";
469fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            }
47078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
47178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
47278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
47378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // android.hardware.foo@2.2::IFoo exists. Now make sure
47478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // @2.2::IFoo extends @2.1::IFoo. If any interface IFoo in @2.2
47578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        // ensures this, @2.2 passes the enforcement.
47678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        FQName prevFQName(prevPacakge.package(), prevPacakge.version(),
47778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                currentFQName.name());
47878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType() == nullptr) {
47978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend anything. (This is probably IBase.)
48078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
48178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
48278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        if (iface->superType()->fqName() != prevFQName) {
48378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo doesn't extend @2.1::IFoo.
484fe07bffd9381605a6f96848a71489a4987363277Yifan Hong            if (iface->superType()->fqName().getPackageAndVersion() ==
485fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                    prevPacakge.getPackageAndVersion()) {
48678b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                LOG(ERROR) << "Cannot enforce minor version uprevs for " << currentPackage.string()
48778b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << ": " << iface->fqName().string() << " extends "
48878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                           << iface->superType()->fqName().string() << ", which is not allowed.";
48978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong                return UNKNOWN_ERROR;
49078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            }
49178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // @2.2::IFoo extends something from a package with a different package name.
49278b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            // Check the next interface.
49378b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong            continue;
49478b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        }
49578b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
496fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // @2.2::IFoo passes. Check next interface.
497fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        extendedInterface = true;
49878b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong        LOG(VERBOSE) << "enforceMinorVersionUprevs: " << currentFQName.string() << " passes.";
49978b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong    }
50078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
501fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    if (!extendedInterface) {
502fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        // No interface extends the interface with the same name in @x.(y-1).
503fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        LOG(ERROR) << currentPackage.string() << " doesn't pass minor version uprev requirement. "
504fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "Requires at least one interface to extend an interface with the same name "
505fe07bffd9381605a6f96848a71489a4987363277Yifan Hong                   << "from " << prevPacakge.string() << ".";
506fe07bffd9381605a6f96848a71489a4987363277Yifan Hong        return UNKNOWN_ERROR;
507fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    }
508fe07bffd9381605a6f96848a71489a4987363277Yifan Hong
509fe07bffd9381605a6f96848a71489a4987363277Yifan Hong    return OK;
51078b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong}
51178b38d1e36934a60b3abcd82d576b54ca254b323Yifan Hong
51228b9b537a4941ac9e4ef2e25e64e3ffc4b833676Steven Morelandstatus_t Coordinator::enforceHashes(const FQName &currentPackage) const {
513218625af26dea71d188361598c1f8c273716830eSteven Moreland    status_t err = OK;
514218625af26dea71d188361598c1f8c273716830eSteven Moreland    std::vector<FQName> packageInterfaces;
515218625af26dea71d188361598c1f8c273716830eSteven Moreland    err = appendPackageInterfacesToVector(currentPackage, &packageInterfaces);
516218625af26dea71d188361598c1f8c273716830eSteven Moreland    if (err != OK) {
517218625af26dea71d188361598c1f8c273716830eSteven Moreland        return err;
518218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
519218625af26dea71d188361598c1f8c273716830eSteven Moreland
520218625af26dea71d188361598c1f8c273716830eSteven Moreland    for (const FQName &currentFQName : packageInterfaces) {
521218625af26dea71d188361598c1f8c273716830eSteven Moreland        AST *ast = parse(currentFQName);
522218625af26dea71d188361598c1f8c273716830eSteven Moreland
523218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (ast == nullptr) {
524218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
525218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
526218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
527218625af26dea71d188361598c1f8c273716830eSteven Moreland
5285bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::string hashPath = getPackageRootPath(currentFQName) + "/current.txt";
529218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string error;
5305bdfa70833286d9085888e0d2843857b9be7d6b2Steven Moreland        std::vector<std::string> frozen = Hash::lookupHash(hashPath, currentFQName.string(), &error);
531218625af26dea71d188361598c1f8c273716830eSteven Moreland
532218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (error.size() > 0) {
533218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << error;
534218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
535218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
536218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
537218625af26dea71d188361598c1f8c273716830eSteven Moreland
538218625af26dea71d188361598c1f8c273716830eSteven Moreland        // hash not define, interface not frozen
539218625af26dea71d188361598c1f8c273716830eSteven Moreland        if (frozen.size() == 0) {
540218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
541218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
542218625af26dea71d188361598c1f8c273716830eSteven Moreland
543218625af26dea71d188361598c1f8c273716830eSteven Moreland        std::string currentHash = Hash::getHash(ast->getFilename()).hexString();
544218625af26dea71d188361598c1f8c273716830eSteven Moreland
545218625af26dea71d188361598c1f8c273716830eSteven Moreland        if(std::find(frozen.begin(), frozen.end(), currentHash) == frozen.end()) {
546218625af26dea71d188361598c1f8c273716830eSteven Moreland            LOG(ERROR) << currentFQName.string() << " has hash " << currentHash
547218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << " which does not match hash on record. This interface has "
548218625af26dea71d188361598c1f8c273716830eSteven Moreland                       << "been frozen. Do not change it!";
549218625af26dea71d188361598c1f8c273716830eSteven Moreland            err = UNKNOWN_ERROR;
550218625af26dea71d188361598c1f8c273716830eSteven Moreland            continue;
551218625af26dea71d188361598c1f8c273716830eSteven Moreland        }
552218625af26dea71d188361598c1f8c273716830eSteven Moreland    }
553218625af26dea71d188361598c1f8c273716830eSteven Moreland
554218625af26dea71d188361598c1f8c273716830eSteven Moreland    return err;
555218625af26dea71d188361598c1f8c273716830eSteven Moreland}
556218625af26dea71d188361598c1f8c273716830eSteven Moreland
557d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
558d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
559d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
560d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
561d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
562d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
563d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
564d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
565d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
566d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
567d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
568d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
569d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
570d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
571d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
572d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
573d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
574d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
575d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
576d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
577d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
578d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
579d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
580d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
581d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
582d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
583d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
584d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
5855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
5865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
587