blob: ea23623d3b6cea22263c6a5ad9dc83547ec4599a [file] [log] [blame]
Chenjie Yu80f91122018-01-31 20:24:50 -08001/*
2 * Copyright (C) 2018 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#define DEBUG false // STOPSHIP if true
18#include "Log.h"
19
20#include "StatsPullerManagerImpl.h"
Chenjie Yu80f91122018-01-31 20:24:50 -080021#include "puller_util.h"
22#include "statslog.h"
23
24namespace android {
25namespace os {
26namespace statsd {
27
28using std::map;
29using std::shared_ptr;
30using std::vector;
31
Yao Chen8a8d16c2018-02-08 14:50:40 -080032namespace {
Chenjie Yu80f91122018-01-31 20:24:50 -080033bool shouldMerge(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
Yao Chen8a8d16c2018-02-08 14:50:40 -080034 const vector<int>& nonAdditiveFields) {
35 const auto& l_values = lhs->getValues();
36 const auto& r_values = rhs->getValues();
37
38 for (size_t i : nonAdditiveFields) {
39 // We store everything starting from index 0, so we need to use i-1
40 if (!(l_values.size() > i - 1 && r_values.size() > i - 1 &&
41 l_values[i - 1].mValue == r_values[i - 1].mValue)) {
42 return false;
43 }
Chenjie Yu80f91122018-01-31 20:24:50 -080044 }
Yao Chen8a8d16c2018-02-08 14:50:40 -080045 return true;
Chenjie Yu80f91122018-01-31 20:24:50 -080046}
47
48// merge rhs to lhs
Yao Chen8a8d16c2018-02-08 14:50:40 -080049// when calling this function, all sanity check should be done already.
50// e.g., index boundary, nonAdditiveFields matching etc.
51bool mergeEvent(shared_ptr<LogEvent>& lhs, shared_ptr<LogEvent>& rhs,
52 const vector<int>& additiveFields) {
53 vector<FieldValue>* host_values = lhs->getMutableValues();
54 const auto& child_values = rhs->getValues();
55 for (int i : additiveFields) {
56 Value& host = (*host_values)[i - 1].mValue;
57 const Value& child = (child_values[i - 1]).mValue;
58 if (child.getType() != host.getType()) {
59 return false;
60 }
61 switch (child.getType()) {
62 case INT:
63 host.setInt(host.int_value + child.int_value);
64 break;
65 case LONG:
66 host.setLong(host.long_value + child.long_value);
67 break;
68 default:
69 ALOGE("Tried to merge 2 fields with unsupported type");
70 return false;
71 }
Chenjie Yu80f91122018-01-31 20:24:50 -080072 }
Yao Chen8a8d16c2018-02-08 14:50:40 -080073 return true;
Chenjie Yu80f91122018-01-31 20:24:50 -080074}
75
Yao Chen8a8d16c2018-02-08 14:50:40 -080076bool tryMerge(vector<shared_ptr<LogEvent>>& data, int child_pos, const vector<int>& host_pos,
77 const vector<int>& nonAdditiveFields, const vector<int>& additiveFields) {
78 for (const auto& pos : host_pos) {
79 if (shouldMerge(data[pos], data[child_pos], nonAdditiveFields) &&
80 mergeEvent(data[pos], data[child_pos], additiveFields)) {
81 return true;
Chenjie Yu80f91122018-01-31 20:24:50 -080082 }
Chenjie Yu80f91122018-01-31 20:24:50 -080083 }
Yao Chen8a8d16c2018-02-08 14:50:40 -080084 return false;
85}
86
87} // namespace
88
89/**
90 * Process all data and merge isolated with host if necessary.
91 * For example:
92 * NetworkBytesAtom {
93 * int uid = 1;
94 * State process_state = 2;
95 * int byte_send = 3;
96 * int byte_recv = 4;
97 * }
98 * additive fields are {3, 4}, non-additive field is {2}
99 * If we pulled the following events (uid1_child is an isolated uid which maps to uid1):
100 * [uid1, fg, 100, 200]
101 * [uid1_child, fg, 100, 200]
102 * [uid1, bg, 100, 200]
103 *
104 * We want to merge them and results should be:
105 * [uid1, fg, 200, 400]
106 * [uid1, bg, 100, 200]
107 */
108void mergeIsolatedUidsToHostUid(vector<shared_ptr<LogEvent>>& data, const sp<UidMap>& uidMap,
109 int tagId) {
110 if (StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId) ==
111 StatsPullerManagerImpl::kAllPullAtomInfo.end()) {
112 VLOG("Unknown pull atom id %d", tagId);
113 return;
Chenjie Yu80f91122018-01-31 20:24:50 -0800114 }
Yao Chenc40a19d2018-03-15 16:48:25 -0700115 if (android::util::AtomsInfo::kAtomsWithUidField.find(tagId) ==
116 android::util::AtomsInfo::kAtomsWithUidField.end()) {
Yao Chen8a8d16c2018-02-08 14:50:40 -0800117 VLOG("No uid to merge for atom %d", tagId);
118 return;
Chenjie Yu80f91122018-01-31 20:24:50 -0800119 }
Yao Chen8a8d16c2018-02-08 14:50:40 -0800120 const vector<int>& additiveFields =
121 StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)->second.additiveFields;
122 const vector<int>& nonAdditiveFields =
123 StatsPullerManagerImpl::kAllPullAtomInfo.find(tagId)->second.nonAdditiveFields;
124
125 // map of host uid to their position in the original vector
126 map<int, vector<int>> hostPosition;
127 vector<bool> toRemove = vector<bool>(data.size(), false);
128
129 for (size_t i = 0; i < data.size(); i++) {
130 vector<FieldValue>* valueList = data[i]->getMutableValues();
131
132 int err = 0;
133 int uid = data[i]->GetInt(1, &err);
134 if (err != 0) {
135 VLOG("Bad uid field for %s", data[i]->ToString().c_str());
136 return;
137 }
138
139 const int hostUid = uidMap->getHostUidOrSelf(uid);
140
141 if (hostUid != uid) {
142 (*valueList)[0].mValue.setInt(hostUid);
143 }
144 if (hostPosition.find(hostUid) == hostPosition.end()) {
145 hostPosition[hostUid].push_back(i);
146 } else {
147 if (tryMerge(data, i, hostPosition[hostUid], nonAdditiveFields, additiveFields)) {
148 toRemove[i] = true;
149 } else {
150 hostPosition[hostUid].push_back(i);
151 }
152 }
153 }
154
155 vector<shared_ptr<LogEvent>> mergedData;
156 for (size_t i = 0; i < toRemove.size(); i++) {
157 if (!toRemove[i]) {
158 mergedData.push_back(data[i]);
159 }
160 }
161 data.clear();
162 data = mergedData;
Chenjie Yu80f91122018-01-31 20:24:50 -0800163}
164
165} // namespace statsd
166} // namespace os
167} // namespace android