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 #pragma once
18 
19 #include "FieldValue.h"
20 
21 #include <android/os/StatsLogEventWrapper.h>
22 #include <android/util/ProtoOutputStream.h>
23 #include <log/log_read.h>
24 #include <private/android_logger.h>
25 
26 #include <string>
27 #include <vector>
28 
29 namespace android {
30 namespace os {
31 namespace statsd {
32 
33 struct AttributionNodeInternal {
set_uidAttributionNodeInternal34     void set_uid(int32_t id) {
35         mUid = id;
36     }
37 
set_tagAttributionNodeInternal38     void set_tag(const std::string& value) {
39         mTag = value;
40     }
41 
uidAttributionNodeInternal42     int32_t uid() const {
43         return mUid;
44     }
45 
tagAttributionNodeInternal46     const std::string& tag() const {
47         return mTag;
48     }
49 
50     int32_t mUid;
51     std::string mTag;
52 };
53 
54 struct InstallTrainInfo {
55     int64_t trainVersionCode;
56     std::string trainName;
57     int32_t status;
58     std::vector<int64_t> experimentIds;
59 };
60 
61 /**
62  * Wrapper for the log_msg structure.
63  */
64 class LogEvent {
65 public:
66     /**
67      * Read a LogEvent from a log_msg.
68      */
69     explicit LogEvent(log_msg& msg);
70 
71     /**
72      * Creates LogEvent from StatsLogEventWrapper.
73      */
74     static void createLogEvents(const StatsLogEventWrapper& statsLogEventWrapper,
75                                 std::vector<std::shared_ptr<LogEvent>>& logEvents);
76 
77     /**
78      * Construct one LogEvent from a StatsLogEventWrapper with the i-th work chain. -1 if no chain.
79      */
80     explicit LogEvent(const StatsLogEventWrapper& statsLogEventWrapper, int workChainIndex);
81 
82     /**
83      * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
84      */
85     explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
86 
87     // For testing. The timestamp is used as both elapsed real time and logd timestamp.
88     explicit LogEvent(int32_t tagId, int64_t timestampNs);
89 
90     // For testing. The timestamp is used as both elapsed real time and logd timestamp.
91     explicit LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid);
92 
93     /**
94      * Constructs a KeyValuePairsAtom LogEvent from value maps.
95      */
96     explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
97                       int32_t uid,
98                       const std::map<int32_t, int32_t>& int_map,
99                       const std::map<int32_t, int64_t>& long_map,
100                       const std::map<int32_t, std::string>& string_map,
101                       const std::map<int32_t, float>& float_map);
102 
103     // Constructs a BinaryPushStateChanged LogEvent from API call.
104     explicit LogEvent(const std::string& trainName, int64_t trainVersionCode, bool requiresStaging,
105                       bool rollbackEnabled, bool requiresLowLatencyMonitor, int32_t state,
106                       const std::vector<uint8_t>& experimentIds, int32_t userId);
107 
108     explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
109                       const InstallTrainInfo& installTrainInfo);
110 
111     ~LogEvent();
112 
113     /**
114      * Get the timestamp associated with this event.
115      */
GetLogdTimestampNs()116     inline int64_t GetLogdTimestampNs() const { return mLogdTimestampNs; }
GetElapsedTimestampNs()117     inline int64_t GetElapsedTimestampNs() const { return mElapsedTimestampNs; }
118 
119     /**
120      * Get the tag for this event.
121      */
GetTagId()122     inline int GetTagId() const { return mTagId; }
123 
GetUid()124     inline uint32_t GetUid() const {
125         return mLogUid;
126     }
127 
128     /**
129      * Get the nth value, starting at 1.
130      *
131      * Returns BAD_INDEX if the index is larger than the number of elements.
132      * Returns BAD_TYPE if the index is available but the data is the wrong type.
133      */
134     int64_t GetLong(size_t key, status_t* err) const;
135     int GetInt(size_t key, status_t* err) const;
136     const char* GetString(size_t key, status_t* err) const;
137     bool GetBool(size_t key, status_t* err) const;
138     float GetFloat(size_t key, status_t* err) const;
139 
140     /**
141      * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
142      * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
143      */
144     bool write(uint32_t value);
145     bool write(int32_t value);
146     bool write(uint64_t value);
147     bool write(int64_t value);
148     bool write(const std::string& value);
149     bool write(float value);
150     bool write(const std::vector<AttributionNodeInternal>& nodes);
151     bool write(const AttributionNodeInternal& node);
152     bool writeKeyValuePairs(int32_t uid,
153                             const std::map<int32_t, int32_t>& int_map,
154                             const std::map<int32_t, int64_t>& long_map,
155                             const std::map<int32_t, std::string>& string_map,
156                             const std::map<int32_t, float>& float_map);
157 
158     /**
159      * Return a string representation of this event.
160      */
161     std::string ToString() const;
162 
163     /**
164      * Write this object to a ProtoOutputStream.
165      */
166     void ToProto(android::util::ProtoOutputStream& out) const;
167 
168     /**
169      * Used with the constructor where tag is passed in. Converts the log_event_list to read mode
170      * and prepares the list for reading.
171      */
172     void init();
173 
174     /**
175      * Set elapsed timestamp if the original timestamp is missing.
176      */
setElapsedTimestampNs(int64_t timestampNs)177     void setElapsedTimestampNs(int64_t timestampNs) {
178         mElapsedTimestampNs = timestampNs;
179     }
180 
181     /**
182      * Set the timestamp if the original logd timestamp is missing.
183      */
setLogdWallClockTimestampNs(int64_t timestampNs)184     void setLogdWallClockTimestampNs(int64_t timestampNs) {
185         mLogdTimestampNs = timestampNs;
186     }
187 
size()188     inline int size() const {
189         return mValues.size();
190     }
191 
getValues()192     const std::vector<FieldValue>& getValues() const {
193         return mValues;
194     }
195 
getMutableValues()196     std::vector<FieldValue>* getMutableValues() {
197         return &mValues;
198     }
199 
makeCopy()200     inline LogEvent makeCopy() {
201         return LogEvent(*this);
202     }
203 
204 private:
205     /**
206      * Only use this if copy is absolutely needed.
207      */
208     LogEvent(const LogEvent&);
209 
210     /**
211      * Parses a log_msg into a LogEvent object.
212      */
213     void init(android_log_context context);
214 
215     // The items are naturally sorted in DFS order as we read them. this allows us to do fast
216     // matching.
217     std::vector<FieldValue> mValues;
218 
219     // This field is used when statsD wants to create log event object and write fields to it. After
220     // calling init() function, this object would be destroyed to save memory usage.
221     // When the log event is created from log msg, this field is never initiated.
222     android_log_context mContext = NULL;
223 
224     // The timestamp set by the logd.
225     int64_t mLogdTimestampNs;
226 
227     // The elapsed timestamp set by statsd log writer.
228     int64_t mElapsedTimestampNs;
229 
230     int mTagId;
231 
232     uint32_t mLogUid;
233 };
234 
235 void writeExperimentIdsToProto(const std::vector<int64_t>& experimentIds, std::vector<uint8_t>* protoOut);
236 
237 }  // namespace statsd
238 }  // namespace os
239 }  // namespace android
240