Loading cmds/incidentd/src/IncidentService.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ static Status checkIncidentPermissions(const IncidentReportArgs& args) { uid_t callingUid = IPCThreadState::self()->getCallingUid(); pid_t callingPid = IPCThreadState::self()->getCallingPid(); if (callingUid == AID_ROOT || callingUid == AID_SHELL) { // root doesn't have permission.DUMP if don't do this! return Status::ok(); Loading @@ -54,13 +55,13 @@ checkIncidentPermissions(const IncidentReportArgs& args) // checking calling permission. if (!checkCallingPermission(DUMP_PERMISSION)) { ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP", IPCThreadState::self()->getCallingPid(), callingUid); callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission: android.permission.DUMP"); } if (!checkCallingPermission(USAGE_STATS_PERMISSION)) { ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS", IPCThreadState::self()->getCallingPid(), callingUid); callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission: android.permission.USAGE_STATS"); } Loading @@ -68,13 +69,17 @@ checkIncidentPermissions(const IncidentReportArgs& args) // checking calling request uid permission. switch (args.dest()) { case DEST_LOCAL: if (callingUid != AID_SHELL || callingUid != AID_ROOT) { if (callingUid != AID_SHELL && callingUid != AID_ROOT) { ALOGW("Calling pid %d and uid %d does not have permission to get local data.", callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission to get local data."); } case DEST_EXPLICIT: if (callingUid != AID_SHELL || callingUid != AID_ROOT || callingUid != AID_STATSD || callingUid != AID_SYSTEM) { if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD && callingUid != AID_SYSTEM) { ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.", callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission to get explicit data."); } Loading cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ statsd_common_src := \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/subscriber/IncidentdReporter.cpp \ src/subscriber/SubscriberReporter.cpp \ src/HashableDimensionKey.cpp \ src/guardrail/MemoryLeakTrackUtil.cpp \ Loading cmds/statsd/src/anomaly/AnomalyTracker.cpp +14 −35 Original line number Diff line number Diff line Loading @@ -19,13 +19,11 @@ #include "AnomalyTracker.h" #include "external/Perfetto.h" #include "guardrail/StatsdStats.h" #include "frameworks/base/libs/incident/proto/android/os/header.pb.h" #include "guardrail/StatsdStats.h" #include "subscriber/IncidentdReporter.h" #include "subscriber/SubscriberReporter.h" #include <android/os/IIncidentManager.h> #include <android/os/IncidentReportArgs.h> #include <binder/IServiceManager.h> #include <statslog.h> #include <time.h> Loading @@ -38,8 +36,7 @@ AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey) : mAlert(alert), mConfigKey(configKey), mNumOfPastBuckets(mAlert.num_buckets() - 1) { VLOG("AnomalyTracker() called"); if (mAlert.num_buckets() <= 0) { ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets()); ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets()); return; } if (!mAlert.has_trigger_if_sum_gt()) { Loading Loading @@ -169,8 +166,8 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const Metric // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this. addPastBucket(key, 0, currentBucketNum - 1); } return mAlert.has_trigger_if_sum_gt() && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); return mAlert.has_trigger_if_sum_gt() && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); } void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) { Loading Loading @@ -231,44 +228,26 @@ void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) { return; } std::set<int> incidentdSections; for (const Subscription& subscription : mSubscriptions) { switch (subscription.subscriber_information_case()) { case Subscription::SubscriberInformationCase::kIncidentdDetails: for (int i = 0; i < subscription.incidentd_details().section_size(); i++) { incidentdSections.insert(subscription.incidentd_details().section(i)); if (!GenerateIncidentReport(subscription.incidentd_details(), mAlert, mConfigKey)) { ALOGW("Failed to generate incident report."); } break; case Subscription::SubscriberInformationCase::kPerfettoDetails: CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details()); if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details())) { ALOGW("Failed to generate prefetto traces."); } break; case Subscription::SubscriberInformationCase::kBroadcastSubscriberDetails: SubscriberReporter::getInstance() .alertBroadcastSubscriber(mConfigKey, subscription, key); SubscriberReporter::getInstance().alertBroadcastSubscriber(mConfigKey, subscription, key); break; default: break; } } if (!incidentdSections.empty()) { sp<IIncidentManager> service = interface_cast<IIncidentManager>( defaultServiceManager()->getService(android::String16("incident"))); if (service != NULL) { IncidentReportArgs incidentReport; for (const auto section : incidentdSections) { incidentReport.addSection(section); } android::os::IncidentHeaderProto header; header.set_alert_id(mAlert.id()); header.mutable_config_key()->set_uid(mConfigKey.GetUid()); header.mutable_config_key()->set_id(mConfigKey.GetId()); incidentReport.addHeader(header); service->reportIncident(incidentReport); } else { ALOGW("Couldn't get the incident service."); } } } } // namespace statsd Loading cmds/statsd/src/anomaly/AnomalyTracker.h +12 −10 Original line number Diff line number Diff line Loading @@ -16,22 +16,24 @@ #pragma once #include <memory> // unique_ptr #include <stdlib.h> #include <gtest/gtest_prod.h> #include <utils/RefBase.h> #include "AnomalyMonitor.h" #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert #include "stats_util.h" // HashableDimensionKey and DimToValMap #include <memory> // unique_ptr #include <stdlib.h> #include <utils/RefBase.h> namespace android { namespace os { namespace statsd { using std::unordered_map; using std::shared_ptr; using std::unordered_map; // Does NOT allow negative values. class AnomalyTracker : public virtual RefBase { Loading Loading @@ -60,8 +62,7 @@ public: // Detects the alert and informs the incidentd when applicable. void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum, const MetricDimensionKey& key, const int64_t& currentBucketValue); const MetricDimensionKey& key, const int64_t& currentBucketValue); // Init the AnomalyMonitor which is shared across anomaly trackers. virtual void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) { Loading Loading @@ -92,7 +93,8 @@ public: // Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker, // and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor. virtual void informAlarmsFired(const uint64_t& timestampNs, virtual void informAlarmsFired( const uint64_t& timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) { return; // The base AnomalyTracker class doesn't have alarms. } Loading cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +5 −6 Original line number Diff line number Diff line Loading @@ -53,7 +53,6 @@ void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const MetricDimensionK void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& timestampNs) { uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC); if (isInRefractoryPeriod(timestampNs, dimensionKey)) { VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period"); Loading Loading @@ -86,15 +85,15 @@ void DurationAnomalyTracker::stopAllAlarms() { } } void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs, void DurationAnomalyTracker::informAlarmsFired( const uint64_t& timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) { if (firedAlarms.empty() || mAlarms.empty()) return; // Find the intersection of firedAlarms and mAlarms. // The for loop is inefficient, since it loops over all keys, but that's okay since it is very // seldomly called. The alternative would be having AnomalyAlarms store information about the // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that is // rarely ever called. // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that // is rarely ever called. unordered_map<MetricDimensionKey, sp<const AnomalyAlarm>> matchedAlarms; for (const auto& kv : mAlarms) { if (firedAlarms.count(kv.second) > 0) { Loading Loading
cmds/incidentd/src/IncidentService.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ static Status checkIncidentPermissions(const IncidentReportArgs& args) { uid_t callingUid = IPCThreadState::self()->getCallingUid(); pid_t callingPid = IPCThreadState::self()->getCallingPid(); if (callingUid == AID_ROOT || callingUid == AID_SHELL) { // root doesn't have permission.DUMP if don't do this! return Status::ok(); Loading @@ -54,13 +55,13 @@ checkIncidentPermissions(const IncidentReportArgs& args) // checking calling permission. if (!checkCallingPermission(DUMP_PERMISSION)) { ALOGW("Calling pid %d and uid %d does not have permission: android.permission.DUMP", IPCThreadState::self()->getCallingPid(), callingUid); callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission: android.permission.DUMP"); } if (!checkCallingPermission(USAGE_STATS_PERMISSION)) { ALOGW("Calling pid %d and uid %d does not have permission: android.permission.USAGE_STATS", IPCThreadState::self()->getCallingPid(), callingUid); callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission: android.permission.USAGE_STATS"); } Loading @@ -68,13 +69,17 @@ checkIncidentPermissions(const IncidentReportArgs& args) // checking calling request uid permission. switch (args.dest()) { case DEST_LOCAL: if (callingUid != AID_SHELL || callingUid != AID_ROOT) { if (callingUid != AID_SHELL && callingUid != AID_ROOT) { ALOGW("Calling pid %d and uid %d does not have permission to get local data.", callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission to get local data."); } case DEST_EXPLICIT: if (callingUid != AID_SHELL || callingUid != AID_ROOT || callingUid != AID_STATSD || callingUid != AID_SYSTEM) { if (callingUid != AID_SHELL && callingUid != AID_ROOT && callingUid != AID_STATSD && callingUid != AID_SYSTEM) { ALOGW("Calling pid %d and uid %d does not have permission to get explicit data.", callingPid, callingUid); return Status::fromExceptionCode(Status::EX_SECURITY, "Calling process does not have permission to get explicit data."); } Loading
cmds/statsd/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ statsd_common_src := \ src/storage/StorageManager.cpp \ src/StatsLogProcessor.cpp \ src/StatsService.cpp \ src/subscriber/IncidentdReporter.cpp \ src/subscriber/SubscriberReporter.cpp \ src/HashableDimensionKey.cpp \ src/guardrail/MemoryLeakTrackUtil.cpp \ Loading
cmds/statsd/src/anomaly/AnomalyTracker.cpp +14 −35 Original line number Diff line number Diff line Loading @@ -19,13 +19,11 @@ #include "AnomalyTracker.h" #include "external/Perfetto.h" #include "guardrail/StatsdStats.h" #include "frameworks/base/libs/incident/proto/android/os/header.pb.h" #include "guardrail/StatsdStats.h" #include "subscriber/IncidentdReporter.h" #include "subscriber/SubscriberReporter.h" #include <android/os/IIncidentManager.h> #include <android/os/IncidentReportArgs.h> #include <binder/IServiceManager.h> #include <statslog.h> #include <time.h> Loading @@ -38,8 +36,7 @@ AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey) : mAlert(alert), mConfigKey(configKey), mNumOfPastBuckets(mAlert.num_buckets() - 1) { VLOG("AnomalyTracker() called"); if (mAlert.num_buckets() <= 0) { ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets()); ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets()); return; } if (!mAlert.has_trigger_if_sum_gt()) { Loading Loading @@ -169,8 +166,8 @@ bool AnomalyTracker::detectAnomaly(const int64_t& currentBucketNum, const Metric // TODO: This creates a needless 0 entry in mSumOverPastBuckets. Fix this. addPastBucket(key, 0, currentBucketNum - 1); } return mAlert.has_trigger_if_sum_gt() && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); return mAlert.has_trigger_if_sum_gt() && getSumOverPastBuckets(key) + currentBucketValue > mAlert.trigger_if_sum_gt(); } void AnomalyTracker::declareAnomaly(const uint64_t& timestampNs, const MetricDimensionKey& key) { Loading Loading @@ -231,44 +228,26 @@ void AnomalyTracker::informSubscribers(const MetricDimensionKey& key) { return; } std::set<int> incidentdSections; for (const Subscription& subscription : mSubscriptions) { switch (subscription.subscriber_information_case()) { case Subscription::SubscriberInformationCase::kIncidentdDetails: for (int i = 0; i < subscription.incidentd_details().section_size(); i++) { incidentdSections.insert(subscription.incidentd_details().section(i)); if (!GenerateIncidentReport(subscription.incidentd_details(), mAlert, mConfigKey)) { ALOGW("Failed to generate incident report."); } break; case Subscription::SubscriberInformationCase::kPerfettoDetails: CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details()); if (!CollectPerfettoTraceAndUploadToDropbox(subscription.perfetto_details())) { ALOGW("Failed to generate prefetto traces."); } break; case Subscription::SubscriberInformationCase::kBroadcastSubscriberDetails: SubscriberReporter::getInstance() .alertBroadcastSubscriber(mConfigKey, subscription, key); SubscriberReporter::getInstance().alertBroadcastSubscriber(mConfigKey, subscription, key); break; default: break; } } if (!incidentdSections.empty()) { sp<IIncidentManager> service = interface_cast<IIncidentManager>( defaultServiceManager()->getService(android::String16("incident"))); if (service != NULL) { IncidentReportArgs incidentReport; for (const auto section : incidentdSections) { incidentReport.addSection(section); } android::os::IncidentHeaderProto header; header.set_alert_id(mAlert.id()); header.mutable_config_key()->set_uid(mConfigKey.GetUid()); header.mutable_config_key()->set_id(mConfigKey.GetId()); incidentReport.addHeader(header); service->reportIncident(incidentReport); } else { ALOGW("Couldn't get the incident service."); } } } } // namespace statsd Loading
cmds/statsd/src/anomaly/AnomalyTracker.h +12 −10 Original line number Diff line number Diff line Loading @@ -16,22 +16,24 @@ #pragma once #include <memory> // unique_ptr #include <stdlib.h> #include <gtest/gtest_prod.h> #include <utils/RefBase.h> #include "AnomalyMonitor.h" #include "config/ConfigKey.h" #include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert #include "stats_util.h" // HashableDimensionKey and DimToValMap #include <memory> // unique_ptr #include <stdlib.h> #include <utils/RefBase.h> namespace android { namespace os { namespace statsd { using std::unordered_map; using std::shared_ptr; using std::unordered_map; // Does NOT allow negative values. class AnomalyTracker : public virtual RefBase { Loading Loading @@ -60,8 +62,7 @@ public: // Detects the alert and informs the incidentd when applicable. void detectAndDeclareAnomaly(const uint64_t& timestampNs, const int64_t& currBucketNum, const MetricDimensionKey& key, const int64_t& currentBucketValue); const MetricDimensionKey& key, const int64_t& currentBucketValue); // Init the AnomalyMonitor which is shared across anomaly trackers. virtual void setAnomalyMonitor(const sp<AnomalyMonitor>& anomalyMonitor) { Loading Loading @@ -92,7 +93,8 @@ public: // Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker, // and removes it from firedAlarms. Does NOT remove the alarm from the AnomalyMonitor. virtual void informAlarmsFired(const uint64_t& timestampNs, virtual void informAlarmsFired( const uint64_t& timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) { return; // The base AnomalyTracker class doesn't have alarms. } Loading
cmds/statsd/src/anomaly/DurationAnomalyTracker.cpp +5 −6 Original line number Diff line number Diff line Loading @@ -53,7 +53,6 @@ void DurationAnomalyTracker::declareAnomalyIfAlarmExpired(const MetricDimensionK void DurationAnomalyTracker::startAlarm(const MetricDimensionKey& dimensionKey, const uint64_t& timestampNs) { uint32_t timestampSec = static_cast<uint32_t>(timestampNs / NS_PER_SEC); if (isInRefractoryPeriod(timestampNs, dimensionKey)) { VLOG("Skipping setting anomaly alarm since it'd fall in the refractory period"); Loading Loading @@ -86,15 +85,15 @@ void DurationAnomalyTracker::stopAllAlarms() { } } void DurationAnomalyTracker::informAlarmsFired(const uint64_t& timestampNs, void DurationAnomalyTracker::informAlarmsFired( const uint64_t& timestampNs, unordered_set<sp<const AnomalyAlarm>, SpHash<AnomalyAlarm>>& firedAlarms) { if (firedAlarms.empty() || mAlarms.empty()) return; // Find the intersection of firedAlarms and mAlarms. // The for loop is inefficient, since it loops over all keys, but that's okay since it is very // seldomly called. The alternative would be having AnomalyAlarms store information about the // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that is // rarely ever called. // DurationAnomalyTracker and key, but that's a lot of data overhead to speed up something that // is rarely ever called. unordered_map<MetricDimensionKey, sp<const AnomalyAlarm>> matchedAlarms; for (const auto& kv : mAlarms) { if (firedAlarms.count(kv.second) > 0) { Loading