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
17 #include "check_valid.h"
18 #include "aidl.h"
19
20 #include <vector>
21
22 namespace android {
23 namespace aidl {
24
25 using TypePredicate = std::function<bool(const AidlTypeSpecifier&)>;
26
27 namespace {
IsListOf(const AidlTypeSpecifier & type,TypePredicate pred)28 bool IsListOf(const AidlTypeSpecifier& type, TypePredicate pred) {
29 return type.GetName() == "List" && type.IsGeneric() && type.GetTypeParameters().size() == 1 &&
30 pred(*type.GetTypeParameters().at(0));
31 }
IsArrayOf(const AidlTypeSpecifier & type,TypePredicate pred)32 bool IsArrayOf(const AidlTypeSpecifier& type, TypePredicate pred) {
33 return type.IsArray() && pred(type);
34 }
IsInterface(const AidlTypeSpecifier & type)35 bool IsInterface(const AidlTypeSpecifier& type) {
36 return type.GetDefinedType() && type.GetDefinedType()->AsInterface();
37 }
38 } // namespace
39
40 struct CheckTypeVisitor : AidlVisitor {
41 bool success = true;
42 std::vector<TypePredicate> checkers;
43
Visitandroid::aidl::CheckTypeVisitor44 void Visit(const AidlTypeSpecifier& type) override {
45 for (auto& checker : checkers) {
46 if (!checker(type)) {
47 success = false;
48 }
49 }
50 }
51
Checkandroid::aidl::CheckTypeVisitor52 void Check(TypePredicate checker) { checkers.push_back(std::move(checker)); }
53 };
54
CheckValid(const AidlDocument & doc,const Options & options)55 bool CheckValid(const AidlDocument& doc, const Options& options) {
56 const auto lang = options.TargetLanguage();
57 const auto min_sdk_version = options.GetMinSdkVersion();
58
59 CheckTypeVisitor v;
60
61 v.Check([&](const AidlTypeSpecifier& type) {
62 const auto valid_version = MinSdkVersionFromString("Tiramisu").value();
63 if ((IsListOf(type, IsInterface) || IsArrayOf(type, IsInterface)) &&
64 lang == Options::Language::JAVA && min_sdk_version < valid_version) {
65 const auto kind = IsListOf(type, IsInterface) ? "List" : "Array";
66 AIDL_ERROR(type) << kind << " of interfaces is available since SDK = " << valid_version
67 << " in Java. Current min_sdk_version is " << min_sdk_version << ".";
68 return false;
69 }
70 return true;
71 });
72
73 v.Check([&](const AidlTypeSpecifier& type) {
74 const auto valid_version = MinSdkVersionFromString("S").value();
75 if (type.GetName() == "ParcelableHolder" && min_sdk_version < valid_version) {
76 AIDL_ERROR(type) << " ParcelableHolder is available since SDK = " << valid_version
77 << ". Current min_sdk_version is " << min_sdk_version << ".";
78 return false;
79 }
80 return true;
81 });
82
83 VisitTopDown(v, doc);
84 return v.success;
85 }
86
87 } // namespace aidl
88 } // namespace android
89