1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "utils.h"
17
18 #include <sstream>
19
20 #include "parse_string.h"
21
22 namespace android::vintf::details {
23
convertLegacyInstanceIntoFqInstance(const std::string & package,const Version & version,const std::string & interface,const std::string & instance,HalFormat format,std::string * appendedError)24 std::optional<FqInstance> convertLegacyInstanceIntoFqInstance(
25 const std::string& package, const Version& version, const std::string& interface,
26 const std::string& instance, HalFormat format, std::string* appendedError) {
27 // Attempt to construct a good error message.
28 std::stringstream ss;
29 ss << "Invalid instance: '";
30 if (format == HalFormat::AIDL) {
31 ss << toAidlFqnameString(package, interface, instance) << " (@" << version.minorVer << ")";
32 } else {
33 ss << toFQNameString(package, version, interface, instance);
34 }
35 ss << "'. ";
36
37 // Attempt to guess the source of error.
38 bool foundError = false;
39 details::FQName fqName;
40 if (!fqName.setTo(package)) {
41 ss << "Package '" << package
42 << "' should have the format [a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*)*";
43 foundError = true;
44 }
45
46 switch (format) {
47 case HalFormat::HIDL:
48 case HalFormat::AIDL: {
49 if (!fqName.setTo(interface) || !fqName.isInterfaceName()) {
50 ss << "Interface '" << interface << "' should have the format I[a-zA-Z0-9_]*";
51 foundError = true;
52 }
53 } break;
54 case HalFormat::NATIVE: {
55 if (!interface.empty() && (!fqName.setTo(interface) || !fqName.isInterfaceName())) {
56 ss << "Interface '" << interface << "' should have the format I[a-zA-Z0-9_]*";
57 foundError = true;
58 }
59 } break;
60 }
61
62 if (foundError) {
63 if (appendedError != nullptr) {
64 *appendedError += ss.str() + "\n";
65 }
66 return std::nullopt;
67 }
68
69 // AIDL HAL <fqname> never contains version
70 std::optional<FqInstance> parsed;
71 switch (format) {
72 case HalFormat::HIDL:
73 case HalFormat::NATIVE:
74 parsed = FqInstance::from(version.majorVer, version.minorVer, interface, instance);
75 break;
76 case HalFormat::AIDL:
77 // AIDL HAL <fqname> never contains version
78 parsed = FqInstance::from(interface, instance);
79 break;
80 }
81 if (!parsed.has_value()) {
82 if (appendedError != nullptr) {
83 std::string debugString = format == HalFormat::AIDL
84 ? toAidlFqnameString(package, interface, instance)
85 : toFQNameString(package, version, interface, instance);
86
87 *appendedError += "Invalid FqInstance: " + debugString + "\n";
88 }
89 }
90
91 return parsed;
92 }
93
94 } // namespace android::vintf::details
95