blob: 0ed2d75802da98165e9c8c1010d5b48e3561df6b [file] [log] [blame]
Yi Jinafb36062018-01-31 19:14:25 -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 */
Yangster-mac754e29e2018-05-02 12:23:17 -070016#define DEBUG false
Yi Jinafb36062018-01-31 19:14:25 -080017#include "Log.h"
18
Yao Chen4ce07292019-02-13 13:06:36 -080019#include "FieldValue.h"
Yi Jinafb36062018-01-31 19:14:25 -080020#include "IncidentdReporter.h"
Yao Chen4ce07292019-02-13 13:06:36 -080021#include "packages/UidMap.h"
22#include "stats_log_util.h"
Yi Jinafb36062018-01-31 19:14:25 -080023
24#include <android/os/IIncidentManager.h>
25#include <android/os/IncidentReportArgs.h>
Yao Chenec216482019-02-06 16:45:40 -080026#include <android/util/ProtoOutputStream.h>
Yi Jinafb36062018-01-31 19:14:25 -080027#include <binder/IBinder.h>
28#include <binder/IServiceManager.h>
29
Yao Chenec216482019-02-06 16:45:40 -080030#include <vector>
31
Yi Jinafb36062018-01-31 19:14:25 -080032namespace android {
33namespace os {
34namespace statsd {
35
Yao Chenec216482019-02-06 16:45:40 -080036using android::util::ProtoOutputStream;
37using std::vector;
38
39using util::FIELD_TYPE_MESSAGE;
40using util::FIELD_TYPE_INT32;
41using util::FIELD_TYPE_INT64;
42
43// field ids in IncidentHeaderProto
44const int FIELD_ID_ALERT_ID = 1;
45const int FIELD_ID_CONFIG_KEY = 3;
46const int FIELD_ID_CONFIG_KEY_UID = 1;
47const int FIELD_ID_CONFIG_KEY_ID = 2;
48
Yao Chen4ce07292019-02-13 13:06:36 -080049const int FIELD_ID_TRIGGER_DETAILS = 4;
50const int FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC = 1;
51const int FIELD_ID_METRIC_VALUE_METRIC_ID = 1;
52const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT = 2;
53const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION = 3;
54const int FIELD_ID_METRIC_VALUE_VALUE = 4;
55
56const int FIELD_ID_PACKAGE_INFO = 3;
57
Yao Chenec216482019-02-06 16:45:40 -080058namespace {
Yao Chen4ce07292019-02-13 13:06:36 -080059void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensionKey& dimensionKey,
60 int64_t metricValue, const ConfigKey& configKey, vector<uint8_t>* protoData) {
Yao Chenec216482019-02-06 16:45:40 -080061 ProtoOutputStream headerProto;
62 headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
63 uint64_t token =
64 headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_CONFIG_KEY);
65 headerProto.write(FIELD_TYPE_INT32 | FIELD_ID_CONFIG_KEY_UID, configKey.GetUid());
66 headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId());
67 headerProto.end(token);
68
Yao Chen4ce07292019-02-13 13:06:36 -080069 token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS);
70
71 // MetricValue trigger_metric = 1;
72 uint64_t metricToken =
73 headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC);
74 // message MetricValue {
75 // optional int64 metric_id = 1;
76 headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_METRIC_ID, (long long)metricId);
77 // optional DimensionsValue dimension_in_what = 2;
78 uint64_t dimToken =
79 headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT);
80 writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), nullptr, &headerProto);
81 headerProto.end(dimToken);
82
83 // optional DimensionsValue dimension_in_condition = 3;
84 dimToken = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION);
85 writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), nullptr, &headerProto);
86 headerProto.end(dimToken);
87
88 // optional int64 value = 4;
89 headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_VALUE, (long long)metricValue);
90
91 // }
92 headerProto.end(metricToken);
93
94 // write relevant uid package info
95 std::set<int32_t> uids;
96
97 for (const auto& dim : dimensionKey.getDimensionKeyInWhat().getValues()) {
98 int uid = getUidIfExists(dim);
99 // any uid <= 2000 are predefined AID_*
100 if (uid > 2000) {
101 uids.insert(uid);
102 }
103 }
104
105 for (const auto& dim : dimensionKey.getDimensionKeyInCondition().getValues()) {
106 int uid = getUidIfExists(dim);
107 if (uid > 2000) {
108 uids.insert(uid);
109 }
110 }
111
112 if (!uids.empty()) {
113 uint64_t token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PACKAGE_INFO);
114 UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true, uids,
115 nullptr /*string set*/, &headerProto);
116 headerProto.end(token);
117 }
118
119 headerProto.end(token);
120
Yao Chenec216482019-02-06 16:45:40 -0800121 protoData->resize(headerProto.size());
122 size_t pos = 0;
123 auto iter = headerProto.data();
124 while (iter.readBuffer() != NULL) {
125 size_t toRead = iter.currentToRead();
126 std::memcpy(&((*protoData)[pos]), iter.readBuffer(), toRead);
127 pos += toRead;
128 iter.rp()->move(toRead);
129 }
130}
131} // namespace
132
Yao Chen4ce07292019-02-13 13:06:36 -0800133bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId,
134 const MetricDimensionKey& dimensionKey, int64_t metricValue,
Yi Jinafb36062018-01-31 19:14:25 -0800135 const ConfigKey& configKey) {
136 if (config.section_size() == 0) {
Yangster-mac932ecec2018-02-01 10:23:52 -0800137 VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id,
Yao Chenec216482019-02-06 16:45:40 -0800138 configKey.GetUid(), (long long)configKey.GetId());
Yi Jinafb36062018-01-31 19:14:25 -0800139 return false;
140 }
141
142 IncidentReportArgs incidentReport;
143
Yao Chenec216482019-02-06 16:45:40 -0800144 vector<uint8_t> protoData;
Yao Chen4ce07292019-02-13 13:06:36 -0800145 getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey, &protoData);
Yao Chenec216482019-02-06 16:45:40 -0800146 incidentReport.addHeader(protoData);
Yi Jinafb36062018-01-31 19:14:25 -0800147
148 for (int i = 0; i < config.section_size(); i++) {
149 incidentReport.addSection(config.section(i));
150 }
151
152 uint8_t dest;
153 switch (config.dest()) {
154 case IncidentdDetails_Destination_AUTOMATIC:
155 dest = android::os::DEST_AUTOMATIC;
156 break;
157 case IncidentdDetails_Destination_EXPLICIT:
158 dest = android::os::DEST_EXPLICIT;
159 break;
160 default:
161 dest = android::os::DEST_AUTOMATIC;
162 }
163 incidentReport.setDest(dest);
164
165 sp<IIncidentManager> service = interface_cast<IIncidentManager>(
166 defaultServiceManager()->getService(android::String16("incident")));
167 if (service == nullptr) {
168 ALOGW("Failed to fetch incident service.");
169 return false;
170 }
171 VLOG("Calling incidentd %p", service.get());
172 binder::Status s = service->reportIncident(incidentReport);
173 VLOG("Report incident status: %s", s.toString8().string());
174 return s.isOk();
175}
176
177} // namespace statsd
178} // namespace os
179} // namespace android