• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 "ApiChecker.h"
18 
19 #include <string>
20 #include <unordered_map>
21 
22 using android::base::Result;
23 
24 namespace {
25 
CompareProps(const sysprop::Properties & latest,const sysprop::Properties & current)26 Result<void> CompareProps(const sysprop::Properties& latest,
27                           const sysprop::Properties& current) {
28   std::unordered_map<std::string, sysprop::Property> props;
29 
30   for (int i = 0; i < current.prop_size(); ++i) {
31     const auto& prop = current.prop(i);
32     props[prop.api_name()] = prop;
33   }
34 
35   std::string err;
36 
37   bool latest_empty = true;
38   for (int i = 0; i < latest.prop_size(); ++i) {
39     const auto& latest_prop = latest.prop(i);
40     if (latest_prop.deprecated() || latest_prop.scope() == sysprop::Internal) {
41       continue;
42     }
43 
44     latest_empty = false;
45 
46     auto itr = props.find(latest_prop.api_name());
47     if (itr == props.end()) {
48       err += "Prop " + latest_prop.api_name() + " has been removed\n";
49       continue;
50     }
51 
52     const auto& current_prop = itr->second;
53 
54     if (latest_prop.type() != current_prop.type()) {
55       err += "Type of prop " + latest_prop.api_name() + " has been changed\n";
56     }
57     // Readonly > Writeonce > ReadWrite
58     if (latest_prop.access() > current_prop.access()) {
59       err += "Accessibility of prop " + latest_prop.api_name() +
60              " has become more restrictive\n";
61     }
62     // Public < Internal
63     if (latest_prop.scope() < current_prop.scope()) {
64       err += "Scope of prop " + latest_prop.api_name() +
65              " has become more restrictive\n";
66     }
67     if (latest_prop.prop_name() != current_prop.prop_name()) {
68       err += "Underlying property of prop " + latest_prop.api_name() +
69              " has been changed\n";
70     }
71     if (latest_prop.enum_values() != current_prop.enum_values()) {
72       err += "Enum values of prop " + latest_prop.api_name() +
73              " has been changed\n";
74     }
75     if (latest_prop.integer_as_bool() != current_prop.integer_as_bool()) {
76       err += "Integer-as-bool of prop " + latest_prop.api_name() +
77              " has been changed\n";
78     }
79   }
80 
81   if (!latest_empty) {
82     if (latest.owner() != current.owner()) {
83       err += "owner of module " + latest.module() + " has been changed\n";
84     }
85   }
86 
87   if (err.empty())
88     return {};
89   else
90     return Errorf("{}", err);
91 }
92 
93 }  // namespace
94 
CompareApis(const sysprop::SyspropLibraryApis & latest,const sysprop::SyspropLibraryApis & current)95 Result<void> CompareApis(const sysprop::SyspropLibraryApis& latest,
96                          const sysprop::SyspropLibraryApis& current) {
97   std::unordered_map<std::string, sysprop::Properties> propsMap;
98 
99   for (int i = 0; i < current.props_size(); ++i) {
100     propsMap[current.props(i).module()] = current.props(i);
101   }
102 
103   for (int i = 0; i < latest.props_size(); ++i) {
104     // Checking whether propsMap contains latest.props(i)->module() or not
105     // is intentionally skipped to handle the case that latest.props(i) has
106     // only deprecated properties.
107     if (auto res =
108             CompareProps(latest.props(i), propsMap[latest.props(i).module()]);
109         !res.ok()) {
110       return res;
111     }
112   }
113 
114   return {};
115 }
116