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/util/ProtoOutputStream.h>
22#include <log/log_event_list.h>
23#include <log/log_read.h>
24#include <private/android_logger.h>
25#include <utils/Errors.h>
26
27#include <string>
28#include <vector>
29
30namespace android {
31namespace os {
32namespace statsd {
33
34struct AttributionNodeInternal {
35    void set_uid(int32_t id) {
36        mUid = id;
37    }
38
39    void set_tag(const std::string& value) {
40        mTag = value;
41    }
42
43    int32_t uid() const {
44        return mUid;
45    }
46
47    const std::string& tag() const {
48        return mTag;
49    }
50
51    int32_t mUid;
52    std::string mTag;
53};
54/**
55 * Wrapper for the log_msg structure.
56 */
57class LogEvent {
58public:
59    /**
60     * Read a LogEvent from a log_msg.
61     */
62    explicit LogEvent(log_msg& msg);
63
64    /**
65     * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
66     */
67    explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
68
69    // For testing. The timestamp is used as both elapsed real time and logd timestamp.
70    explicit LogEvent(int32_t tagId, int64_t timestampNs);
71
72    ~LogEvent();
73
74    /**
75     * Get the timestamp associated with this event.
76     */
77    inline int64_t GetLogdTimestampNs() const { return mLogdTimestampNs; }
78    inline int64_t GetElapsedTimestampNs() const { return mElapsedTimestampNs; }
79
80    /**
81     * Get the tag for this event.
82     */
83    inline int GetTagId() const { return mTagId; }
84
85    inline uint32_t GetUid() const {
86        return mLogUid;
87    }
88
89    /**
90     * Get the nth value, starting at 1.
91     *
92     * Returns BAD_INDEX if the index is larger than the number of elements.
93     * Returns BAD_TYPE if the index is available but the data is the wrong type.
94     */
95    int64_t GetLong(size_t key, status_t* err) const;
96    int GetInt(size_t key, status_t* err) const;
97    const char* GetString(size_t key, status_t* err) const;
98    bool GetBool(size_t key, status_t* err) const;
99    float GetFloat(size_t key, status_t* err) const;
100
101    /**
102     * Write test data to the LogEvent. This can only be used when the LogEvent is constructed
103     * using LogEvent(tagId, timestampNs). You need to call init() before you can read from it.
104     */
105    bool write(uint32_t value);
106    bool write(int32_t value);
107    bool write(uint64_t value);
108    bool write(int64_t value);
109    bool write(const std::string& value);
110    bool write(float value);
111    bool write(const std::vector<AttributionNodeInternal>& nodes);
112    bool write(const AttributionNodeInternal& node);
113
114    /**
115     * Return a string representation of this event.
116     */
117    std::string ToString() const;
118
119    /**
120     * Write this object to a ProtoOutputStream.
121     */
122    void ToProto(android::util::ProtoOutputStream& out) const;
123
124    /**
125     * Used with the constructor where tag is passed in. Converts the log_event_list to read mode
126     * and prepares the list for reading.
127     */
128    void init();
129
130    /**
131     * Set elapsed timestamp if the original timestamp is missing.
132     */
133    void setElapsedTimestampNs(int64_t timestampNs) {
134        mElapsedTimestampNs = timestampNs;
135    }
136
137    /**
138     * Set the timestamp if the original logd timestamp is missing.
139     */
140    void setLogdWallClockTimestampNs(int64_t timestampNs) {
141        mLogdTimestampNs = timestampNs;
142    }
143
144    inline int size() const {
145        return mValues.size();
146    }
147
148    const std::vector<FieldValue>& getValues() const {
149        return mValues;
150    }
151
152    std::vector<FieldValue>* getMutableValues() {
153        return &mValues;
154    }
155
156private:
157    /**
158     * Don't copy, it's slower. If we really need this we can add it but let's try to
159     * avoid it.
160     */
161    explicit LogEvent(const LogEvent&);
162
163    /**
164     * Parses a log_msg into a LogEvent object.
165     */
166    void init(android_log_context context);
167
168    // The items are naturally sorted in DFS order as we read them. this allows us to do fast
169    // matching.
170    std::vector<FieldValue> mValues;
171
172    // This field is used when statsD wants to create log event object and write fields to it. After
173    // calling init() function, this object would be destroyed to save memory usage.
174    // When the log event is created from log msg, this field is never initiated.
175    android_log_context mContext = NULL;
176
177    // The timestamp set by the logd.
178    int64_t mLogdTimestampNs;
179
180    // The elapsed timestamp set by statsd log writer.
181    int64_t mElapsedTimestampNs;
182
183    int mTagId;
184
185    uint32_t mLogUid;
186};
187
188}  // namespace statsd
189}  // namespace os
190}  // namespace android
191
192