• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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