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 #ifndef ANDROID_STATS_LOG_STATS_EVENT_H
18 #define ANDROID_STATS_LOG_STATS_EVENT_H
19 
20 #include <stdbool.h>
21 #include <stddef.h>
22 #include <stdint.h>
23 
24 /*
25  * Functionality to build and store the buffer sent over the statsd socket.
26  * This code defines and encapsulates the socket protocol.
27  *
28  * Usage:
29  *      struct stats_event* event = stats_event_obtain();
30  *
31  *      stats_event_set_atom_id(event, atomId);
32  *      stats_event_write_int32(event, 24);
33  *      stats_event_add_bool_annotation(event, 1, true); // annotations apply to the previous field
34  *      stats_event_add_int32_annotation(event, 2, 128);
35  *      stats_event_write_float(event, 2.0);
36  *
37  *      stats_event_build(event);
38  *      stats_event_write(event);
39  *      stats_event_release(event);
40  *
41  * Notes:
42  *    (a) write_<type>() and add_<type>_annotation() should be called in the order that fields
43  *        and annotations are defined in the atom.
44  *    (b) set_atom_id() can be called anytime before stats_event_write().
45  *    (c) add_<type>_annotation() calls apply to the previous field.
46  *    (d) If errors occur, stats_event_write() will write a bitmask of the errors to the socket.
47  *    (e) All strings should be encoded using UTF8.
48  */
49 
50 /* ERRORS */
51 #define ERROR_NO_TIMESTAMP 0x1
52 #define ERROR_NO_ATOM_ID 0x2
53 #define ERROR_OVERFLOW 0x4
54 #define ERROR_ATTRIBUTION_CHAIN_TOO_LONG 0x8
55 #define ERROR_TOO_MANY_KEY_VALUE_PAIRS 0x10
56 #define ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD 0x20
57 #define ERROR_INVALID_ANNOTATION_ID 0x40
58 #define ERROR_ANNOTATION_ID_TOO_LARGE 0x80
59 #define ERROR_TOO_MANY_ANNOTATIONS 0x100
60 #define ERROR_TOO_MANY_FIELDS 0x200
61 #define ERROR_INVALID_VALUE_TYPE 0x400
62 #define ERROR_STRING_NOT_NULL_TERMINATED 0x800
63 
64 /* TYPE IDS */
65 #define INT32_TYPE 0x00
66 #define INT64_TYPE 0x01
67 #define STRING_TYPE 0x02
68 #define LIST_TYPE 0x03
69 #define FLOAT_TYPE 0x04
70 #define BOOL_TYPE 0x05
71 #define BYTE_ARRAY_TYPE 0x06
72 #define OBJECT_TYPE 0x07
73 #define KEY_VALUE_PAIRS_TYPE 0x08
74 #define ATTRIBUTION_CHAIN_TYPE 0x09
75 #define ERROR_TYPE 0x0F
76 
77 #ifdef __cplusplus
78 extern "C" {
79 #endif  // __CPLUSPLUS
80 
81 struct stats_event;
82 
83 /* SYSTEM API */
84 struct stats_event* stats_event_obtain();
85 // The build function can be called multiple times without error. If the event
86 // has been built before, this function is a no-op.
87 void stats_event_build(struct stats_event* event);
88 int stats_event_write(struct stats_event* event);
89 void stats_event_release(struct stats_event* event);
90 
91 void stats_event_set_atom_id(struct stats_event* event, uint32_t atomId);
92 
93 void stats_event_write_int32(struct stats_event* event, int32_t value);
94 void stats_event_write_int64(struct stats_event* event, int64_t value);
95 void stats_event_write_float(struct stats_event* event, float value);
96 void stats_event_write_bool(struct stats_event* event, bool value);
97 
98 void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes);
99 
100 // Buf must be null-terminated.
101 void stats_event_write_string8(struct stats_event* event, const char* value);
102 
103 // Tags must be null-terminated.
104 void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
105                                          const char* const* tags, uint8_t numNodes);
106 
107 /* key_value_pair struct can be constructed as follows:
108  *    struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE,
109  *                                  .stringValue = buf};
110  */
111 struct key_value_pair {
112     int32_t key;
113     uint8_t valueType;  // expected to be INT32_TYPE, INT64_TYPE, FLOAT_TYPE, or STRING_TYPE
114     union {
115         int32_t int32Value;
116         int64_t int64Value;
117         float floatValue;
118         const char* stringValue;  // must be null terminated
119     };
120 };
121 
122 void stats_event_write_key_value_pairs(struct stats_event* event, struct key_value_pair* pairs,
123                                        uint8_t numPairs);
124 
125 void stats_event_add_bool_annotation(struct stats_event* event, uint8_t annotationId, bool value);
126 void stats_event_add_int32_annotation(struct stats_event* event, uint8_t annotationId,
127                                       int32_t value);
128 
129 uint32_t stats_event_get_atom_id(struct stats_event* event);
130 // Size is an output parameter.
131 uint8_t* stats_event_get_buffer(struct stats_event* event, size_t* size);
132 uint32_t stats_event_get_errors(struct stats_event* event);
133 
134 // This table is used by StatsEventCompat to access the stats_event API.
135 struct stats_event_api_table {
136     struct stats_event* (*obtain)(void);
137     void (*build)(struct stats_event*);
138     int (*write)(struct stats_event*);
139     void (*release)(struct stats_event*);
140     void (*set_atom_id)(struct stats_event*, uint32_t);
141     void (*write_int32)(struct stats_event*, int32_t);
142     void (*write_int64)(struct stats_event*, int64_t);
143     void (*write_float)(struct stats_event*, float);
144     void (*write_bool)(struct stats_event*, bool);
145     void (*write_byte_array)(struct stats_event*, const uint8_t*, size_t);
146     void (*write_string8)(struct stats_event*, const char*);
147     void (*write_attribution_chain)(struct stats_event*, const uint32_t*, const char* const*,
148                                     uint8_t);
149     void (*write_key_value_pairs)(struct stats_event*, struct key_value_pair*, uint8_t);
150     void (*add_bool_annotation)(struct stats_event*, uint8_t, bool);
151     void (*add_int32_annotation)(struct stats_event*, uint8_t, int32_t);
152     uint32_t (*get_atom_id)(struct stats_event*);
153     uint8_t* (*get_buffer)(struct stats_event*, size_t*);
154     uint32_t (*get_errors)(struct stats_event*);
155 };
156 
157 // exposed for benchmarking only
158 void stats_event_truncate_buffer(struct stats_event* event, bool truncate);
159 
160 #ifdef __cplusplus
161 }
162 #endif  // __CPLUSPLUS
163 
164 #endif  // ANDROID_STATS_LOG_STATS_EVENT_H
165