1 /*
2  * Copyright (C) 2017, 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 #ifndef ANDROID_STATS_LOG_API_GEN_COLLATION_H
18 #define ANDROID_STATS_LOG_API_GEN_COLLATION_H
19 
20 #include <google/protobuf/descriptor.h>
21 #include <stdint.h>
22 
23 #include <map>
24 #include <set>
25 #include <vector>
26 
27 #include "frameworks/proto_logging/stats/atom_field_options.pb.h"
28 
29 namespace android {
30 namespace stats_log_api_gen {
31 
32 using google::protobuf::Descriptor;
33 using google::protobuf::FieldDescriptor;
34 using std::map;
35 using std::set;
36 using std::shared_ptr;
37 using std::string;
38 using std::vector;
39 
40 const int PULL_ATOM_START_ID = 10000;
41 
42 const int FIRST_UID_IN_CHAIN_ID = 0;
43 
44 /**
45  * The types of oneof atoms.
46  *
47  * `OneofDescriptor::name()` returns the name of the oneof.
48  */
49 const char ONEOF_PUSHED_ATOM_NAME[] = "pushed";
50 const char ONEOF_PULLED_ATOM_NAME[] = "pulled";
51 
52 enum AtomType { ATOM_TYPE_PUSHED, ATOM_TYPE_PULLED };
53 
54 enum AnnotationId : uint8_t {
55     ANNOTATION_ID_IS_UID = 1,
56     ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2,
57     ANNOTATION_ID_PRIMARY_FIELD = 3,
58     ANNOTATION_ID_EXCLUSIVE_STATE = 4,
59     ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5,
60     ANNOTATION_ID_DEFAULT_STATE = 6,
61     ANNOTATION_ID_TRIGGER_STATE_RESET = 7,
62     ANNOTATION_ID_STATE_NESTED = 8,
63     ANNOTATION_ID_RESTRICTION_CATEGORY = 9,
64     ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO = 10,
65     ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE = 11,
66     ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY = 12,
67     ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT = 13,
68     ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY = 14,
69     ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH = 15,
70     ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT = 16,
71     ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING = 17,
72     ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION = 18,
73 };
74 
75 const int ATOM_ID_FIELD_NUMBER = -1;
76 
77 const char DEFAULT_MODULE_NAME[] = "DEFAULT";
78 
79 const std::string UINT_ATOM_ALLOWLIST[22] = {
80         "AppDied",
81         "DevicePolicyEvent",
82         "NfcErrorOccurred",
83         "NfcHceTransactionOccurred",
84         "ScreenTimeoutExtensionReported",
85         "ThreadnetworkTelemetryDataReported",
86         "ThreadnetworkTopoEntryRepeated",
87         "SubsystemSleepState",
88         "BluetoothActivityInfo",
89         "CpuTimePerFreq",
90         "CpuTimePerUid",
91         "CpuTimePerUidFreq",
92         "WifiActivityInfo",
93         "ModemActivityInfo",
94         "SystemElapsedRealtime",
95         "SystemUptime",
96         "CpuActiveTime",
97         "CpuClusterTime",
98         "DiskSpace",
99         "OnDevicePowerMeasurement",
100         "GeneralExternalStorageAccessStats",
101         "CpuTimePerClusterFreq",
102 };
103 
104 /**
105  * The types for atom parameters.
106  */
107 typedef enum {
108     JAVA_TYPE_UNKNOWN_OR_INVALID = 0,
109 
110     JAVA_TYPE_ATTRIBUTION_CHAIN = 1,
111     JAVA_TYPE_BOOLEAN = 2,
112     JAVA_TYPE_INT = 3,
113     JAVA_TYPE_LONG = 4,
114     JAVA_TYPE_FLOAT = 5,
115     JAVA_TYPE_DOUBLE = 6,
116     JAVA_TYPE_STRING = 7,
117     JAVA_TYPE_ENUM = 8,
118     JAVA_TYPE_BOOLEAN_ARRAY = 10,
119     JAVA_TYPE_INT_ARRAY = 11,
120     JAVA_TYPE_LONG_ARRAY = 12,
121     JAVA_TYPE_FLOAT_ARRAY = 13,
122     JAVA_TYPE_DOUBLE_ARRAY = 14,
123     JAVA_TYPE_STRING_ARRAY = 15,
124     JAVA_TYPE_ENUM_ARRAY = 16,
125 
126     JAVA_TYPE_OBJECT = -1,
127     JAVA_TYPE_BYTE_ARRAY = -2,
128 } java_type_t;
129 
130 enum AnnotationType {
131     ANNOTATION_TYPE_UNKNOWN = 0,
132     ANNOTATION_TYPE_INT = 1,
133     ANNOTATION_TYPE_BOOL = 2,
134 };
135 
136 union AnnotationValue {
137     int intValue;
138     bool boolValue;
139 
AnnotationValue(const int value)140     explicit AnnotationValue(const int value) : intValue(value) {
141     }
AnnotationValue(const bool value)142     explicit AnnotationValue(const bool value) : boolValue(value) {
143     }
144 };
145 
146 struct Annotation {
147     const AnnotationId annotationId;
148     const int atomId;
149     AnnotationType type;
150     AnnotationValue value;
151 
AnnotationAnnotation152     inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type,
153                       AnnotationValue value)
154         : annotationId(annotationId), atomId(atomId), type(type), value(value) {
155     }
~AnnotationAnnotation156     inline ~Annotation() {
157     }
158 
159     inline bool operator<(const Annotation& that) const {
160         return atomId == that.atomId ? annotationId < that.annotationId : atomId < that.atomId;
161     }
162 };
163 
164 struct SharedComparator {
165     template <typename T>
operatorSharedComparator166     inline bool operator()(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs) const {
167         return (*lhs) < (*rhs);
168     }
169 };
170 
171 using AnnotationSet = set<shared_ptr<Annotation>, SharedComparator>;
172 
173 using FieldNumberToAnnotations = map<int, AnnotationSet>;
174 
175 /**
176  * The name and type for an atom field.
177  */
178 struct AtomField {
179     string name;
180     java_type_t javaType;
181 
182     // If the field is of type enum, the following map contains the list of enum
183     // values.
184     map<int /* numeric value */, string /* value name */> enumValues;
185     // If the field is of type enum, the following field contains enum type name
186     string enumTypeName;
187 
AtomFieldAtomField188     inline AtomField() : name(), javaType(JAVA_TYPE_UNKNOWN_OR_INVALID) {
189     }
AtomFieldAtomField190     inline AtomField(const AtomField& that)
191         : name(that.name),
192           javaType(that.javaType),
193           enumValues(that.enumValues),
194           enumTypeName(that.enumTypeName) {
195     }
196 
AtomFieldAtomField197     inline AtomField(string n, java_type_t jt) : name(n), javaType(jt) {
198     }
~AtomFieldAtomField199     inline ~AtomField() {
200     }
201 };
202 
203 /**
204  * The name and code for an atom.
205  */
206 struct AtomDecl {
207     int code;
208     string name;
209 
210     string message;
211     vector<AtomField> fields;
212 
213     AtomType atomType;
214 
215     FieldNumberToAnnotations fieldNumberToAnnotations;
216 
217     vector<int> primaryFields;
218     int exclusiveField = 0;
219     int defaultState = INT_MAX;
220     int triggerStateReset = INT_MAX;
221     bool nested = true;
222     bool restricted = false;
223 
224     AtomDecl();
225     AtomDecl(const AtomDecl& that);
226     AtomDecl(int code, const string& name, const string& message, AtomType atomType);
227     ~AtomDecl();
228 
229     inline bool operator<(const AtomDecl& that) const {
230         return (code == that.code) ? (name < that.name) : (code < that.code);
231     }
232 };
233 
234 using AtomDeclSet = set<shared_ptr<AtomDecl>, SharedComparator>;
235 
236 // Maps a field number to a set of atoms that have annotation(s) for their field with that field
237 // number.
238 using FieldNumberToAtomDeclSet = map<int, AtomDeclSet>;
239 
240 using SignatureInfoMap = map<vector<java_type_t>, FieldNumberToAtomDeclSet>;
241 
242 struct Atoms {
243     SignatureInfoMap signatureInfoMap;
244     SignatureInfoMap pulledAtomsSignatureInfoMap;
245     AtomDeclSet decls;
246     AtomDeclSet non_chained_decls;
247     SignatureInfoMap nonChainedSignatureInfoMap;
248 };
249 
250 /**
251  * Gather the information about the atoms.  Returns the number of errors.
252  */
253 int collate_atoms(const Descriptor& descriptor, const string& moduleName, Atoms& atoms);
254 int collate_atom(const Descriptor& atom, AtomDecl& atomDecl, vector<java_type_t>& signature);
255 
256 }  // namespace stats_log_api_gen
257 }  // namespace android
258 
259 #endif  // ANDROID_STATS_LOG_API_GEN_COLLATION_H
260