Coordinator.cpp revision 5bb14024064a51a044e51c14466e5b2ae8352505
15345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "Coordinator.h"
25345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
35345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include "AST.h"
45345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
55345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber#include <android-base/logging.h>
6dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber#include <iterator>
7d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber#include <sys/dir.h>
8d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber#include <sys/stat.h>
95345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huberextern android::status_t parseFile(android::AST *ast, const char *path);
115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
125345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Hubernamespace android {
135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
14dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::Coordinator(
15dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const std::vector<std::string> &packageRootPaths,
16dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const std::vector<std::string> &packageRoots)
17dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    : mPackageRootPaths(packageRootPaths),
18dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber      mPackageRoots(packageRoots) {
19dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
20dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber}
21dc981333b38f47f416b9b810dc80e5cf2d7ac68aAndreas Huber
22dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::~Coordinator() {
23dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // empty
24dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
255345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas HuberAST *Coordinator::parse(const FQName &fqName) {
2768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
2868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
296e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber    // LOG(INFO) << "parsing " << fqName.string();
306e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
3168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(fqName);
325345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
345345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
355345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        return ast;
365345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
375345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
3868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Add this to the cache immediately, so we can discover circular imports.
3968f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, NULL);
4068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (fqName.name() != "types") {
4268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // Any interface file implicitly imports its package's types.hal.
4368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        FQName typesName(fqName.package(), fqName.version(), "types");
4468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        (void)parse(typesName);
4568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
4668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        // fall through.
4768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
4868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
49dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    std::string path = getPackagePath(fqName);
50dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
5168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(fqName.name());
5268f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    path.append(".hal");
535345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
545345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    AST *ast = new AST(this);
5568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    status_t err = parseFile(ast, path.c_str());
5668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
5768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    if (err != OK) {
586e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        // LOG(ERROR) << "parsing '" << path << "' FAILED.";
596e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
6068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        delete ast;
6168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        ast = NULL;
625345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
6368f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber        return NULL;
6468f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    }
6568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber
66a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (ast->package().package() != fqName.package()
67a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            || ast->package().version() != fqName.version()) {
68a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        LOG(ERROR)
69a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            << "File at '" << path << "' does not match expected package "
70a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            << "and/or version.";
71a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
72a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        err = UNKNOWN_ERROR;
73a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    } else {
74a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        std::string ifaceName;
75a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        if (ast->isInterface(&ifaceName)) {
76a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            if (fqName.name() == "types") {
77a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                LOG(ERROR)
78a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "File at '" << path << "' declares an interface '"
79a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << ifaceName
80a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "' instead of the expected types common to the package.";
81a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
82a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
83a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            } else if (ifaceName != fqName.name()) {
84a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                LOG(ERROR)
85a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "File at '" << path << "' does not declare interface type '"
86a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << fqName.name()
87a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                    << "'.";
88a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
89a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                err = UNKNOWN_ERROR;
90a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            }
91a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        } else if (fqName.name() != "types") {
92a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            LOG(ERROR)
93a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                << "File at '" << path << "' declares types rather than the "
94a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber                << "expected interface type '" << fqName.name() << "'.";
95a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
96a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber            err = UNKNOWN_ERROR;
97a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        }
98a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
99a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
100a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    if (err != OK) {
101a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        delete ast;
102a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        ast = NULL;
103a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
104a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber        return NULL;
105a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber    }
106a2723d26427f7db19777dfed330047253e7a4e1bAndreas Huber
10768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    mCache.add(fqName, ast);
1085345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1095345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return ast;
1105345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1115345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
112dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::vector<std::string>::const_iterator
113dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas HuberCoordinator::findPackageRoot(const FQName &fqName) const {
1145345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.package().empty());
1155345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK(!fqName.version().empty());
1165345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
117dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Find the right package prefix and path for this FQName.  For
118dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // example, if FQName is "android.hardware.nfc@1.0::INfc", and the
119dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix:root is set to [ "android.hardware:hardware/interfaces",
120dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "vendor.qcom.hardware:vendor/qcom"], then we will identify the
121dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // prefix "android.hardware" and the package root
122dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "hardware/interfaces".
123dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
124dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // TODO: This now returns on the first match.  Throw an error if
125dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // there are multiple hits.
126dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = mPackageRoots.begin();
127dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    for (; it != mPackageRoots.end(); it++) {
128dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        if (fqName.package().find(*it) != std::string::npos) {
129dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber            break;
130dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        }
131dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
132dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    CHECK(it != mPackageRoots.end());
133dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
134dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return it;
135dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
136dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
137dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackageRoot(const FQName &fqName) const {
138dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
139dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
140dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    return prefix;
141dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber}
142dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
1435bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstd::string Coordinator::getPackageRootPath(const FQName &fqName) const {
1445bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto it = findPackageRoot(fqName);
1455bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
1465bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev    return root;
1475bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev}
1485bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchev
149dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huberstd::string Coordinator::getPackagePath(
150dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        const FQName &fqName, bool relative) const {
151dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
152dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto it = findPackageRoot(fqName);
153dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto prefix = *it;
154dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    auto root = mPackageRootPaths[std::distance(mPackageRoots.begin(), it)];
155dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
156dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Make sure the prefix ends on a '.' and the root path on a '/'
157dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--prefix.end()) != '.') {
158dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        prefix += '.';
159dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
160dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
161dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    if ((*--root.end()) != '/') {
162dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        root += '/';
163dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    }
164dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber
165dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // Given FQName of "android.hardware.nfc@1.0::IFoo" and a prefix
166dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    // "android.hardware.", the suffix is "nfc@1.0::IFoo".
167dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber    const std::string packageSuffix = fqName.package().substr(prefix.length());
1685345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
169881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    std::string packagePath;
170881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    if (!relative) {
171dca261ff8a8fed807c6e8206360eb84b1ff9e0a9Andreas Huber        packagePath = root;
172881227d860c59471eee31d39946e96ce2daa35d6Andreas Huber    }
1735345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1745345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t startPos = 0;
1755345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos;
1765345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    while ((dotPos = packageSuffix.find('.', startPos)) != std::string::npos) {
1775345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append(packageSuffix.substr(startPos, dotPos - startPos));
1785345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        packagePath.append("/");
1795345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1805345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        startPos = dotPos + 1;
1815345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
1825345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_LT(startPos + 1, packageSuffix.length());
1835345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(packageSuffix.substr(startPos));
1845345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1855345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1865345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    CHECK_EQ(fqName.version().find('@'), 0u);
1875345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append(fqName.version().substr(1));
1885345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    packagePath.append("/");
1895345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1905345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return packagePath;
1915345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
1925345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
193fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas HuberType *Coordinator::lookupType(const FQName &fqName) const {
1945345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    // Fully qualified.
19568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    CHECK(fqName.isFullyQualified());
1965345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
1975345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    std::string topType;
1985345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    size_t dotPos = fqName.name().find('.');
1995345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (dotPos == std::string::npos) {
2005345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name();
2015345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    } else {
2025345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        topType = fqName.name().substr(0, dotPos);
2035345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2045345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
20568f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // Assuming {topType} is the name of an interface type, let's see if the
20668f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    // associated {topType}.hal file was imported.
20768f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName ifaceName(fqName.package(), fqName.version(), topType);
20868f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    ssize_t index = mCache.indexOfKey(ifaceName);
2095345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
2105345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
2116e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        CHECK(ast != NULL);
2126e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber
2135345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        Type *type = ast->lookupTypeInternal(fqName.name());
2145345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2155345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        if (type != NULL) {
216fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas Huber            return type->ref();
2175345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
2185345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2195345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
22068f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    FQName typesName(fqName.package(), fqName.version(), "types");
22168f24590cda230fb92eac44ed0247f54f9b31ad0Andreas Huber    index = mCache.indexOfKey(typesName);
2225345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    if (index >= 0) {
2235345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        AST *ast = mCache.valueAt(index);
2246e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber        if (ast != NULL) {
2256e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            // ast could be NULL if types.hal didn't exist, which is valid.
2266e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            Type *type = ast->lookupTypeInternal(fqName.name());
2275345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2286e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            if (type != NULL) {
229fd4afabde8fb9bbdd0021addeb9fbb62428f2c17Andreas Huber                return type->ref();
2306e584b70065ce37615980aba5ed60d27a54da1c3Andreas Huber            }
2315345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber        }
2325345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    }
2335345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
2345345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber    return NULL;
2355345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}
2365345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
237d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstatus_t Coordinator::getPackageInterfaceFiles(
238d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
239d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<std::string> *fileNames) const {
240d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    fileNames->clear();
2416cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
242d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    const std::string packagePath = getPackagePath(package);
243d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
244d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    DIR *dir = opendir(packagePath.c_str());
245d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
246d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (dir == NULL) {
247d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return -errno;
248d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
249d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
250d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    struct dirent *ent;
251d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((ent = readdir(dir)) != NULL) {
252d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (ent->d_type != DT_REG) {
2536cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber            continue;
2546cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber        }
2556cb08cf9f021a01d9d2b1eaec6729aac6ae70708Andreas Huber
256d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix = ".hal";
257d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto suffix_len = std::strlen(suffix);
258d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const auto d_namelen = strlen(ent->d_name);
259e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
260d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (d_namelen < suffix_len
261d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                || strcmp(ent->d_name + d_namelen - suffix_len, suffix)) {
262d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
263e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber        }
264d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
265d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        fileNames->push_back(std::string(ent->d_name, d_namelen - suffix_len));
266e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    }
267e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
268d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    closedir(dir);
269d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    dir = NULL;
270d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
271e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber    return OK;
272e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber}
273e61e3f7b138a992047a60c4b8c27f1c752ed57baAndreas Huber
2745bb14024064a51a044e51c14466e5b2ae8352505Iliyan Malchevstatus_t Coordinator::appendPackageInterfacesToSet(
275d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        const FQName &package,
276d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::vector<FQName> *packageInterfaces) const {
277d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    packageInterfaces->clear();
278d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
279d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::vector<std::string> fileNames;
280d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    status_t err = getPackageInterfaceFiles(package, &fileNames);
281d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
282d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (err != OK) {
283d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        return err;
284d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
285d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
286d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    for (const auto &fileName : fileNames) {
287d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        FQName subFQName(
288d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                package.package() + package.version() + "::" + fileName);
289d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
290d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (!subFQName.isValid()) {
291d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            LOG(WARNING)
292d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "Whole-package import encountered invalid filename '"
293d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << fileName
294d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << "' in package "
295d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.package()
296d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                << package.version();
297d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
298d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            continue;
299d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
300d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
301d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageInterfaces->push_back(subFQName);
302d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
303d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
304d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return OK;
305d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
306d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
307d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberstd::string Coordinator::convertPackageRootToPath(const FQName &fqName) const {
308d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::string packageRoot = getPackageRoot(fqName);
309d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
310d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    if (*(packageRoot.end()--) != '.') {
311d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        packageRoot += '.';
312d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
313d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
314d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    std::replace(packageRoot.begin(), packageRoot.end(), '.', '/');
315d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
316d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return packageRoot; // now converted to a path
317d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
318d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
319d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber// static
320d2943e11533697b97aa5330f05fc144493748c0bAndreas Huberbool Coordinator::MakeParentHierarchy(const std::string &path) {
321d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    static const mode_t kMode = 0755;
322d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
323d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t start = 1;  // Ignore leading '/'
324d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    size_t slashPos;
325d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    while ((slashPos = path.find("/", start)) != std::string::npos) {
326d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        std::string partial = path.substr(0, slashPos);
327d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
328d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        struct stat st;
329d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        if (stat(partial.c_str(), &st) < 0) {
330d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (errno != ENOENT) {
331d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
332d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
333d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
334d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            int res = mkdir(partial.c_str(), kMode);
335d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            if (res < 0) {
336d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber                return false;
337d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            }
338d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        } else if (!S_ISDIR(st.st_mode)) {
339d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber            return false;
340d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        }
341d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
342d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber        start = slashPos + 1;
343d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    }
344d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
345d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber    return true;
346d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber}
347d2943e11533697b97aa5330f05fc144493748c0bAndreas Huber
3485345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber}  // namespace android
3495345ec2b1b7e4126b77aa2131b231a9eb5ee811dAndreas Huber
350