summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/FieldValue.cpp19
-rw-r--r--cmds/statsd/src/FieldValue.h3
-rw-r--r--cmds/statsd/src/StatsService.cpp2
-rw-r--r--cmds/statsd/src/anomaly/AlarmTracker.cpp4
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.cpp14
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.h8
-rw-r--r--cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp8
-rw-r--r--cmds/statsd/src/anomaly/subscriber_util.cpp13
-rw-r--r--cmds/statsd/src/anomaly/subscriber_util.h7
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp4
-rw-r--r--cmds/statsd/src/metrics/duration_helper/DurationTracker.h4
-rw-r--r--cmds/statsd/src/packages/UidMap.cpp100
-rw-r--r--cmds/statsd/src/packages/UidMap.h15
-rw-r--r--cmds/statsd/src/stats_log.proto14
-rw-r--r--cmds/statsd/src/subscriber/IncidentdReporter.cpp72
-rw-r--r--cmds/statsd/src/subscriber/IncidentdReporter.h4
-rw-r--r--cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp3
-rw-r--r--libs/incident/proto/android/os/header.proto5
20 files changed, 231 insertions, 74 deletions
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 80ed80776829..13f5c8ae5fd8 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -19,6 +19,7 @@
#include "FieldValue.h"
#include "HashableDimensionKey.h"
#include "math.h"
+#include "statslog.h"
namespace android {
namespace os {
@@ -122,6 +123,24 @@ bool isAttributionUidField(const FieldValue& value) {
return false;
}
+int32_t getUidIfExists(const FieldValue& value) {
+ bool isUid = false;
+ // the field is uid field if the field is the uid field in attribution node or marked as
+ // is_uid in atoms.proto
+ if (isAttributionUidField(value)) {
+ isUid = true;
+ } else {
+ auto it = android::util::AtomsInfo::kAtomsWithUidField.find(value.mField.getTag());
+ if (it != android::util::AtomsInfo::kAtomsWithUidField.end()) {
+ int uidField = it->second; // uidField is the field number in proto
+ isUid = value.mField.getDepth() == 0 && value.mField.getPosAtDepth(0) == uidField &&
+ value.mValue.getType() == INT;
+ }
+ }
+
+ return isUid ? value.mValue.int_value : -1;
+}
+
bool isAttributionUidField(const Field& field, const Value& value) {
int f = field.getField() & 0xff007f;
if (f == 0x10001 && value.getType() == INT) {
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index a5d00ac4e72b..6729e052b5ee 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -386,6 +386,9 @@ bool HasPositionALL(const FieldMatcher& matcher);
bool isAttributionUidField(const FieldValue& value);
+/* returns uid if the field is uid field, or -1 if the field is not a uid field */
+int getUidIfExists(const FieldValue& value);
+
void translateFieldMatcher(const FieldMatcher& matcher, std::vector<Matcher>* output);
bool isAttributionUidField(const Field& field, const Value& value);
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index fb603b9ce163..c542b6215c88 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -159,7 +159,7 @@ StatsService::StatsService(const sp<Looper>& handlerLooper)
}
})) {
- mUidMap = new UidMap();
+ mUidMap = UidMap::getInstance();
mPullerManager = new StatsPullerManager();
StatsPuller::SetUidMap(mUidMap);
mConfigManager = new ConfigManager();
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.cpp b/cmds/statsd/src/anomaly/AlarmTracker.cpp
index 8d7369935ea4..019a9f7e5f9a 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.cpp
+++ b/cmds/statsd/src/anomaly/AlarmTracker.cpp
@@ -78,8 +78,8 @@ void AlarmTracker::informAlarmsFired(
}
if (!mSubscriptions.empty()) {
VLOG("AlarmTracker triggers the subscribers.");
- triggerSubscribers(mAlarmConfig.id(), DEFAULT_METRIC_DIMENSION_KEY, mConfigKey,
- mSubscriptions);
+ triggerSubscribers(mAlarmConfig.id(), 0 /*metricId N/A*/, DEFAULT_METRIC_DIMENSION_KEY,
+ 0 /* metricValue N/A */, mConfigKey, mSubscriptions);
}
firedAlarms.erase(mInternalAlarm);
mAlarmSec = findNextAlarmSec((timestampNs-1) / NS_PER_SEC + 1); // round up
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index ee111cddcfd7..d1dcb5df7838 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -207,7 +207,8 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum,
getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt();
}
-void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key) {
+void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, int64_t metricId,
+ const MetricDimensionKey& key, int64_t metricValue) {
// TODO(b/110563466): Why receive timestamp? RefractoryPeriod should always be based on
// real time right now.
if (isInRefractoryPeriod(timestampNs, key)) {
@@ -225,7 +226,7 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime
if (!mSubscriptions.empty()) {
ALOGI("An anomaly (%lld) %s has occurred! Informing subscribers.",
mAlert.id(), key.toString().c_str());
- informSubscribers(key);
+ informSubscribers(key, metricId, metricValue);
} else {
ALOGI("An anomaly has occurred! (But no subscriber for that alert.)");
}
@@ -238,11 +239,11 @@ void AnomalyTracker::declareAnomaly(const int64_t& timestampNs, const MetricDime
}
void AnomalyTracker::detectAndDeclareAnomaly(const int64_t& timestampNs,
- const int64_t& currBucketNum,
+ const int64_t& currBucketNum, int64_t metricId,
const MetricDimensionKey& key,
const int64_t& currentBucketValue) {
if (detectAnomaly(currBucketNum, key, currentBucketValue)) {
- declareAnomaly(timestampNs, key);
+ declareAnomaly(timestampNs, metricId, key, currentBucketValue);
}
}
@@ -255,8 +256,9 @@ bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs,
return false;
}
-void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) {
- triggerSubscribers(mAlert.id(), key, mConfigKey, mSubscriptions);
+void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id,
+ int64_t metricValue) {
+ triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions);
}
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index 927e2df1b53a..e9414735b82b 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -67,14 +67,16 @@ public:
const int64_t& currentBucketValue);
// Informs incidentd about the detected alert.
- void declareAnomaly(const int64_t& timestampNs, const MetricDimensionKey& key);
+ void declareAnomaly(const int64_t& timestampNs, int64_t metricId, const MetricDimensionKey& key,
+ int64_t metricValue);
// Detects if, based on past buckets plus the new currentBucketValue (which generally
// represents the partially-filled current bucket), an anomaly has happened, and if so,
// declares an anomaly and informs relevant subscribers.
// Also advances to currBucketNum-1.
void detectAndDeclareAnomaly(const int64_t& timestampNs, const int64_t& currBucketNum,
- const MetricDimensionKey& key, const int64_t& currentBucketValue);
+ int64_t metricId, const MetricDimensionKey& key,
+ const int64_t& currentBucketValue);
// Init the AlarmMonitor which is shared across anomaly trackers.
virtual void setAlarmMonitor(const sp<AlarmMonitor>& alarmMonitor) {
@@ -176,7 +178,7 @@ protected:
virtual void resetStorage();
// Informs the subscribers (incidentd, perfetto, broadcasts, etc) that an anomaly has occurred.
- void informSubscribers(const MetricDimensionKey& key);
+ void informSubscribers(const MetricDimensionKey& key, int64_t metricId, int64_t metricValue);
FRIEND_TEST(AnomalyTrackerTest, TestConsecutiveBuckets);
FRIEND_TEST(AnomalyTrackerTest, TestSparseBuckets);
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
index 3acfd171848e..2b56810170e5 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp
@@ -65,7 +65,9 @@ void DurationAnomalyTracker::stopAlarm(const MetricDimensionKey& dimensionKey,
// If the alarm is set in the past but hasn't fired yet (due to lag), catch it now.
if (itr->second != nullptr && timestampNs >= (int64_t)NS_PER_SEC * itr->second->timestampSec) {
- declareAnomaly(timestampNs, dimensionKey);
+ declareAnomaly(timestampNs, mAlert.metric_id(), dimensionKey,
+ mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) -
+ itr->second->timestampSec);
}
if (mAlarmMonitor != nullptr) {
mAlarmMonitor->remove(itr->second);
@@ -100,7 +102,9 @@ void DurationAnomalyTracker::informAlarmsFired(const int64_t& timestampNs,
// Now declare each of these alarms to have fired.
for (const auto& kv : matchedAlarms) {
- declareAnomaly(timestampNs, kv.first);
+ declareAnomaly(
+ timestampNs, mAlert.metric_id(), kv.first,
+ mAlert.trigger_if_sum_gt() + (timestampNs / NS_PER_SEC) - kv.second->timestampSec);
mAlarms.erase(kv.first);
firedAlarms.erase(kv.second); // No one else can also own it, so we're done with it.
}
diff --git a/cmds/statsd/src/anomaly/subscriber_util.cpp b/cmds/statsd/src/anomaly/subscriber_util.cpp
index 6b46b8b3b900..548a6869436d 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.cpp
+++ b/cmds/statsd/src/anomaly/subscriber_util.cpp
@@ -30,9 +30,8 @@ namespace android {
namespace os {
namespace statsd {
-void triggerSubscribers(const int64_t rule_id,
- const MetricDimensionKey& dimensionKey,
- const ConfigKey& configKey,
+void triggerSubscribers(int64_t ruleId, int64_t metricId, const MetricDimensionKey& dimensionKey,
+ int64_t metricValue, const ConfigKey& configKey,
const std::vector<Subscription>& subscriptions) {
VLOG("informSubscribers called.");
if (subscriptions.empty()) {
@@ -50,13 +49,14 @@ void triggerSubscribers(const int64_t rule_id,
}
switch (subscription.subscriber_information_case()) {
case Subscription::SubscriberInformationCase::kIncidentdDetails:
- if (!GenerateIncidentReport(subscription.incidentd_details(), rule_id, configKey)) {
+ if (!GenerateIncidentReport(subscription.incidentd_details(), ruleId, metricId,
+ dimensionKey, metricValue, configKey)) {
ALOGW("Failed to generate incident report.");
}
break;
case Subscription::SubscriberInformationCase::kPerfettoDetails:
if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details(),
- subscription.id(), rule_id, configKey)) {
+ subscription.id(), ruleId, configKey)) {
ALOGW("Failed to generate perfetto traces.");
}
break;
@@ -66,7 +66,7 @@ void triggerSubscribers(const int64_t rule_id,
break;
case Subscription::SubscriberInformationCase::kPerfprofdDetails:
if (!CollectPerfprofdTraceAndUploadToDropbox(subscription.perfprofd_details(),
- rule_id, configKey)) {
+ ruleId, configKey)) {
ALOGW("Failed to generate perfprofd traces.");
}
break;
@@ -76,7 +76,6 @@ void triggerSubscribers(const int64_t rule_id,
}
}
-
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/anomaly/subscriber_util.h b/cmds/statsd/src/anomaly/subscriber_util.h
index dba8981a72aa..1df3c8991f94 100644
--- a/cmds/statsd/src/anomaly/subscriber_util.h
+++ b/cmds/statsd/src/anomaly/subscriber_util.h
@@ -24,10 +24,9 @@ namespace android {
namespace os {
namespace statsd {
-void triggerSubscribers(const int64_t rule_id,
- const MetricDimensionKey& dimensionKey,
- const ConfigKey& configKey,
- const std::vector<Subscription>& subscriptions);
+void triggerSubscribers(const int64_t ruleId, const int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
+ const ConfigKey& configKey, const std::vector<Subscription>& subscriptions);
} // namespace statsd
} // namespace os
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 5707de544648..e84f88d407d3 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -303,7 +303,7 @@ void CountMetricProducer::onMatchedLogEventInternalLocked(
if (prev != mCurrentFullCounters->end()) {
countWholeBucket += prev->second;
}
- tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey,
countWholeBucket);
}
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 837d532f7e09..63017936b1db 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -485,8 +485,8 @@ void GaugeMetricProducer::onMatchedLogEventInternalLocked(
gaugeVal = value.long_value;
}
for (auto& tracker : mAnomalyTrackers) {
- tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, eventKey,
- gaugeVal);
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId,
+ eventKey, gaugeVal);
}
}
}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index bc7c8727284f..3cf378d7d7ce 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -697,8 +697,8 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
wholeBucketVal += prev->second;
}
for (auto& tracker : mAnomalyTrackers) {
- tracker->detectAndDeclareAnomaly(
- eventTimeNs, mCurrentBucketNum, eventKey, wholeBucketVal);
+ tracker->detectAndDeclareAnomaly(eventTimeNs, mCurrentBucketNum, mMetricId, eventKey,
+ wholeBucketVal);
}
}
}
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index ccb1d4359e89..081e61ed21fa 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -155,8 +155,8 @@ protected:
const int64_t& currentBucketValue) {
for (auto& anomalyTracker : mAnomalyTrackers) {
if (anomalyTracker != nullptr) {
- anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mEventKey,
- currentBucketValue);
+ anomalyTracker->detectAndDeclareAnomaly(timestamp, currBucketNum, mTrackerId,
+ mEventKey, currentBucketValue);
}
}
}
diff --git a/cmds/statsd/src/packages/UidMap.cpp b/cmds/statsd/src/packages/UidMap.cpp
index 5cf012638dce..d4b57dd68134 100644
--- a/cmds/statsd/src/packages/UidMap.cpp
+++ b/cmds/statsd/src/packages/UidMap.cpp
@@ -73,6 +73,11 @@ UidMap::UidMap() : mBytesUsed(0) {}
UidMap::~UidMap() {}
+sp<UidMap> UidMap::getInstance() {
+ static sp<UidMap> sInstance = new UidMap();
+ return sInstance;
+}
+
bool UidMap::hasApp(int uid, const string& packageName) const {
lock_guard<mutex> lock(mMutex);
@@ -336,6 +341,61 @@ size_t UidMap::getBytesUsed() const {
return mBytesUsed;
}
+void UidMap::writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller, const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto) {
+ lock_guard<mutex> lock(mMutex);
+
+ writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller, interestingUids,
+ str_set, proto);
+}
+
+void UidMap::writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller,
+ const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto) {
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
+ for (const auto& kv : mMap) {
+ if (!interestingUids.empty() &&
+ interestingUids.find(kv.first.first) == interestingUids.end()) {
+ continue;
+ }
+ uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
+ FIELD_ID_SNAPSHOT_PACKAGE_INFO);
+ if (str_set != nullptr) {
+ str_set->insert(kv.first.second);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
+ (long long)Hash64(kv.first.second));
+ if (includeVersionStrings) {
+ str_set->insert(kv.second.versionString);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
+ (long long)Hash64(kv.second.versionString));
+ }
+ if (includeInstaller) {
+ str_set->insert(kv.second.installer);
+ proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
+ (long long)Hash64(kv.second.installer));
+ }
+ } else {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
+ if (includeVersionStrings) {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
+ kv.second.versionString);
+ }
+ if (includeInstaller) {
+ proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
+ kv.second.installer);
+ }
+ }
+
+ proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
+ (long long)kv.second.versionCode);
+ proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
+ proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
+ proto->end(token);
+ }
+}
+
void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::set<string>* str_set,
bool includeVersionStrings, bool includeInstaller,
ProtoOutputStream* proto) {
@@ -381,43 +441,9 @@ void UidMap::appendUidMap(const int64_t& timestamp, const ConfigKey& key, std::s
// Write snapshot from current uid map state.
uint64_t snapshotsToken =
proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_SNAPSHOTS);
- proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_TIMESTAMP, (long long)timestamp);
- for (const auto& kv : mMap) {
- uint64_t token = proto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED |
- FIELD_ID_SNAPSHOT_PACKAGE_INFO);
-
- if (str_set != nullptr) {
- str_set->insert(kv.first.second);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_NAME_HASH,
- (long long)Hash64(kv.first.second));
- if (includeVersionStrings) {
- str_set->insert(kv.second.versionString);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING_HASH,
- (long long)Hash64(kv.second.versionString));
- }
- if (includeInstaller) {
- str_set->insert(kv.second.installer);
- proto->write(FIELD_TYPE_UINT64 | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER_HASH,
- (long long)Hash64(kv.second.installer));
- }
- } else {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_NAME, kv.first.second);
- if (includeVersionStrings) {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_VERSION_STRING,
- kv.second.versionString);
- }
- if (includeInstaller) {
- proto->write(FIELD_TYPE_STRING | FIELD_ID_SNAPSHOT_PACKAGE_INSTALLER,
- kv.second.installer);
- }
- }
-
- proto->write(FIELD_TYPE_INT64 | FIELD_ID_SNAPSHOT_PACKAGE_VERSION,
- (long long)kv.second.versionCode);
- proto->write(FIELD_TYPE_INT32 | FIELD_ID_SNAPSHOT_PACKAGE_UID, kv.first.first);
- proto->write(FIELD_TYPE_BOOL | FIELD_ID_SNAPSHOT_PACKAGE_DELETED, kv.second.deleted);
- proto->end(token);
- }
+ writeUidMapSnapshotLocked(timestamp, includeVersionStrings, includeInstaller,
+ std::set<int32_t>() /*empty uid set means including every uid*/,
+ str_set, proto);
proto->end(snapshotsToken);
int64_t prevMin = getMinimumTimestampNs();
diff --git a/cmds/statsd/src/packages/UidMap.h b/cmds/statsd/src/packages/UidMap.h
index 75ff507ef09a..a7c5fb27375c 100644
--- a/cmds/statsd/src/packages/UidMap.h
+++ b/cmds/statsd/src/packages/UidMap.h
@@ -91,6 +91,8 @@ public:
UidMap();
~UidMap();
static const std::map<std::string, uint32_t> sAidToUidMapping;
+
+ static sp<UidMap> getInstance();
/*
* All three inputs must be the same size, and the jth element in each array refers to the same
* tuple, ie. uid[j] corresponds to packageName[j] with versionCode[j].
@@ -152,12 +154,25 @@ public:
std::set<int32_t> getAppUid(const string& package) const;
+ // Write current PackageInfoSnapshot to ProtoOutputStream.
+ // interestingUids: If not empty, only write the package info for these uids. If empty, write
+ // package info for all uids.
+ // str_set: if not null, add new string to the set and write str_hash to proto
+ // if null, write string to proto.
+ void writeUidMapSnapshot(int64_t timestamp, bool includeVersionStrings, bool includeInstaller,
+ const std::set<int32_t>& interestingUids, std::set<string>* str_set,
+ ProtoOutputStream* proto);
+
private:
std::set<string> getAppNamesFromUidLocked(const int32_t& uid, bool returnNormalized) const;
string normalizeAppName(const string& appName) const;
void getListenerListCopyLocked(std::vector<wp<PackageInfoListener>>* output);
+ void writeUidMapSnapshotLocked(int64_t timestamp, bool includeVersionStrings,
+ bool includeInstaller, const std::set<int32_t>& interestingUids,
+ std::set<string>* str_set, ProtoOutputStream* proto);
+
mutable mutex mMutex;
mutable mutex mIsolatedMutex;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 09b8fed60dcc..623d8bc06e38 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -457,3 +457,17 @@ message StatsdStatsReport {
}
repeated LogLossStats detected_log_loss = 16;
}
+
+message AlertTriggerDetails {
+ message MetricValue {
+ optional int64 metric_id = 1;
+ optional DimensionsValue dimension_in_what = 2;
+ optional DimensionsValue dimension_in_condition = 3;
+ optional int64 value = 4;
+ }
+ oneof value {
+ MetricValue trigger_metric = 1;
+ EventMetricData trigger_event = 2;
+ }
+ optional UidMapping.PackageInfoSnapshot package_info = 3;
+}
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.cpp b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
index 42cac0cc4122..0ed2d75802da 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.cpp
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.cpp
@@ -16,7 +16,10 @@
#define DEBUG false
#include "Log.h"
+#include "FieldValue.h"
#include "IncidentdReporter.h"
+#include "packages/UidMap.h"
+#include "stats_log_util.h"
#include <android/os/IIncidentManager.h>
#include <android/os/IncidentReportArgs.h>
@@ -43,8 +46,18 @@ const int FIELD_ID_CONFIG_KEY = 3;
const int FIELD_ID_CONFIG_KEY_UID = 1;
const int FIELD_ID_CONFIG_KEY_ID = 2;
+const int FIELD_ID_TRIGGER_DETAILS = 4;
+const int FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC = 1;
+const int FIELD_ID_METRIC_VALUE_METRIC_ID = 1;
+const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT = 2;
+const int FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION = 3;
+const int FIELD_ID_METRIC_VALUE_VALUE = 4;
+
+const int FIELD_ID_PACKAGE_INFO = 3;
+
namespace {
-void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uint8_t>* protoData) {
+void getProtoData(const int64_t& rule_id, int64_t metricId, const MetricDimensionKey& dimensionKey,
+ int64_t metricValue, const ConfigKey& configKey, vector<uint8_t>* protoData) {
ProtoOutputStream headerProto;
headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_ALERT_ID, (long long)rule_id);
uint64_t token =
@@ -53,6 +66,58 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin
headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_CONFIG_KEY_ID, (long long)configKey.GetId());
headerProto.end(token);
+ token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS);
+
+ // MetricValue trigger_metric = 1;
+ uint64_t metricToken =
+ headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_TRIGGER_DETAILS_TRIGGER_METRIC);
+ // message MetricValue {
+ // optional int64 metric_id = 1;
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_METRIC_ID, (long long)metricId);
+ // optional DimensionsValue dimension_in_what = 2;
+ uint64_t dimToken =
+ headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_WHAT);
+ writeDimensionToProto(dimensionKey.getDimensionKeyInWhat(), nullptr, &headerProto);
+ headerProto.end(dimToken);
+
+ // optional DimensionsValue dimension_in_condition = 3;
+ dimToken = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_METRIC_VALUE_DIMENSION_IN_CONDITION);
+ writeDimensionToProto(dimensionKey.getDimensionKeyInCondition(), nullptr, &headerProto);
+ headerProto.end(dimToken);
+
+ // optional int64 value = 4;
+ headerProto.write(FIELD_TYPE_INT64 | FIELD_ID_METRIC_VALUE_VALUE, (long long)metricValue);
+
+ // }
+ headerProto.end(metricToken);
+
+ // write relevant uid package info
+ std::set<int32_t> uids;
+
+ for (const auto& dim : dimensionKey.getDimensionKeyInWhat().getValues()) {
+ int uid = getUidIfExists(dim);
+ // any uid <= 2000 are predefined AID_*
+ if (uid > 2000) {
+ uids.insert(uid);
+ }
+ }
+
+ for (const auto& dim : dimensionKey.getDimensionKeyInCondition().getValues()) {
+ int uid = getUidIfExists(dim);
+ if (uid > 2000) {
+ uids.insert(uid);
+ }
+ }
+
+ if (!uids.empty()) {
+ uint64_t token = headerProto.start(FIELD_TYPE_MESSAGE | FIELD_ID_PACKAGE_INFO);
+ UidMap::getInstance()->writeUidMapSnapshot(getElapsedRealtimeNs(), true, true, uids,
+ nullptr /*string set*/, &headerProto);
+ headerProto.end(token);
+ }
+
+ headerProto.end(token);
+
protoData->resize(headerProto.size());
size_t pos = 0;
auto iter = headerProto.data();
@@ -65,7 +130,8 @@ void getProtoData(const int64_t& rule_id, const ConfigKey& configKey, vector<uin
}
} // namespace
-bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
+bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
const ConfigKey& configKey) {
if (config.section_size() == 0) {
VLOG("The alert %lld contains zero section in config(%d,%lld)", (unsigned long long)rule_id,
@@ -76,7 +142,7 @@ bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_
IncidentReportArgs incidentReport;
vector<uint8_t> protoData;
- getProtoData(rule_id, configKey, &protoData);
+ getProtoData(rule_id, metricId, dimensionKey, metricValue, configKey, &protoData);
incidentReport.addHeader(protoData);
for (int i = 0; i < config.section_size(); i++) {
diff --git a/cmds/statsd/src/subscriber/IncidentdReporter.h b/cmds/statsd/src/subscriber/IncidentdReporter.h
index 1b83fe23de8f..e78a4d98dcd8 100644
--- a/cmds/statsd/src/subscriber/IncidentdReporter.h
+++ b/cmds/statsd/src/subscriber/IncidentdReporter.h
@@ -16,6 +16,7 @@
#pragma once
+#include "HashableDimensionKey.h"
#include "config/ConfigKey.h"
#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert, IncidentdDetails
@@ -26,7 +27,8 @@ namespace statsd {
/**
* Calls incidentd to trigger an incident report and put in dropbox for uploading.
*/
-bool GenerateIncidentReport(const IncidentdDetails& config, const int64_t& rule_id,
+bool GenerateIncidentReport(const IncidentdDetails& config, int64_t rule_id, int64_t metricId,
+ const MetricDimensionKey& dimensionKey, int64_t metricValue,
const ConfigKey& configKey);
} // namespace statsd
diff --git a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
index 960fbdab1c15..c10703c36b98 100644
--- a/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
+++ b/cmds/statsd/tests/anomaly/AnomalyTracker_test.cpp
@@ -90,7 +90,8 @@ void detectAndDeclareAnomalies(AnomalyTracker& tracker,
const std::shared_ptr<DimToValMap>& bucket,
const int64_t& eventTimestamp) {
for (const auto& kv : *bucket) {
- tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, kv.first, kv.second);
+ tracker.detectAndDeclareAnomaly(eventTimestamp, bucketNum, 0 /*metric_id*/, kv.first,
+ kv.second);
}
}
diff --git a/libs/incident/proto/android/os/header.proto b/libs/incident/proto/android/os/header.proto
index a84dc48b8b34..d463f87055b3 100644
--- a/libs/incident/proto/android/os/header.proto
+++ b/libs/incident/proto/android/os/header.proto
@@ -37,4 +37,9 @@ message IncidentHeaderProto {
optional int64 id = 2; // The unique id of the statsd config.
}
optional StatsdConfigKey config_key = 3;
+
+ // Details about the trigger. com.android.os.AlertTriggerDetails
+ // Only use bytes type here to avoid indirect dependency on atoms.proto
+ // And this header passes through incidentd without incidentd parsing it.
+ optional bytes trigger_details = 4;
}