1 /*
2  * Copyright (C) 2017 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 #pragma once
18 
19 #include <unordered_map>
20 
21 #include "anomaly/AlarmMonitor.h"
22 #include "anomaly/AlarmTracker.h"
23 #include "anomaly/AnomalyTracker.h"
24 #include "condition/ConditionTracker.h"
25 #include "config/ConfigKey.h"
26 #include "config/ConfigMetadataProvider.h"
27 #include "external/StatsPullerManager.h"
28 #include "guardrail/StatsdStats.h"
29 #include "logd/LogEvent.h"
30 #include "matchers/AtomMatchingTracker.h"
31 #include "metrics/MetricProducer.h"
32 #include "packages/UidMap.h"
33 #include "src/statsd_config.pb.h"
34 #include "src/statsd_metadata.pb.h"
35 
36 namespace android {
37 namespace os {
38 namespace statsd {
39 
40 // A MetricsManager is responsible for managing metrics from one single config source.
41 class MetricsManager : public virtual RefBase,
42                        public virtual PullUidProvider,
43                        public virtual ConfigMetadataProvider {
44 public:
45     MetricsManager(const ConfigKey& configKey, const StatsdConfig& config, int64_t timeBaseNs,
46                    const int64_t currentTimeNs, const sp<UidMap>& uidMap,
47                    const sp<StatsPullerManager>& pullerManager,
48                    const sp<AlarmMonitor>& anomalyAlarmMonitor,
49                    const sp<AlarmMonitor>& periodicAlarmMonitor);
50 
51     virtual ~MetricsManager();
52 
53     bool updateConfig(const StatsdConfig& config, int64_t timeBaseNs, const int64_t currentTimeNs,
54                       const sp<AlarmMonitor>& anomalyAlarmMonitor,
55                       const sp<AlarmMonitor>& periodicAlarmMonitor);
56 
57     // Return whether the configuration is valid.
58     bool isConfigValid() const;
59 
60     virtual void onLogEvent(const LogEvent& event);
61 
62     void onAnomalyAlarmFired(
63             int64_t timestampNs,
64             unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
65 
66     void onPeriodicAlarmFired(
67             int64_t timestampNs,
68             unordered_set<sp<const InternalAlarm>, SpHash<InternalAlarm>>& alarmSet);
69 
70     void notifyAppUpgrade(int64_t eventTimeNs, const string& apk, int uid, int64_t version);
71 
72     void notifyAppRemoved(int64_t eventTimeNs, const string& apk, int uid);
73 
74     void onUidMapReceived(int64_t eventTimeNs);
75 
76     void onStatsdInitCompleted(int64_t elapsedTimeNs);
77 
78     void init();
79 
80     vector<int32_t> getPullAtomUids(int32_t atomId) override;
81 
82     bool useV2SoftMemoryCalculation() override;
83 
shouldWriteToDisk()84     bool shouldWriteToDisk() const {
85         return mNoReportMetricIds.size() != mAllMetricProducers.size();
86     }
87 
shouldPersistLocalHistory()88     bool shouldPersistLocalHistory() const {
89         return mShouldPersistHistory;
90     }
91 
92     void dumpStates(int out, bool verbose);
93 
94     // Does not set the used uids.
getUidMapOptions()95     inline UidMapOptions getUidMapOptions() const {
96         return {.includeVersionStrings = mVersionStringsInReport,
97                 .includeInstaller = mInstallerInReport,
98                 .truncatedCertificateHashSize = mPackageCertificateHashSizeBytes,
99                 .omitSystemUids = mOmitSystemUidsInUidMap,
100                 .omitUnusedUids = mOmitUnusedUidsInUidMap,
101                 .allowlistedPackages = mAllowlistedUidMapPackages};
102     }
103 
isInTtl(const int64_t timestampNs)104     inline bool isInTtl(const int64_t timestampNs) const {
105         return mTtlNs <= 0 || timestampNs < mTtlEndNs;
106     };
107 
hashStringInReport()108     inline bool hashStringInReport() const {
109         return mHashStringsInReport;
110     };
111 
refreshTtl(const int64_t currentTimestampNs)112     void refreshTtl(const int64_t currentTimestampNs) {
113         if (mTtlNs > 0) {
114             mTtlEndNs = currentTimestampNs + mTtlNs;
115         }
116     };
117 
118     // Returns the elapsed realtime when this metric manager last reported metrics. If this config
119     // has not yet dumped any reports, this is the time the metricsmanager was initialized.
getLastReportTimeNs()120     inline int64_t getLastReportTimeNs() const {
121         return mLastReportTimeNs;
122     };
123 
getLastReportWallClockNs()124     inline int64_t getLastReportWallClockNs() const {
125         return mLastReportWallClockNs;
126     };
127 
getNumMetrics()128     inline size_t getNumMetrics() const {
129         return mAllMetricProducers.size();
130     }
131 
132     virtual void dropData(const int64_t dropTimeNs);
133 
134     virtual void onDumpReport(const int64_t dumpTimeNs, int64_t wallClockNs,
135                               const bool include_current_partial_bucket, const bool erase_data,
136                               const DumpLatency dumpLatency, std::set<string>* str_set,
137                               std::set<int32_t>& usedUids,
138                               android::util::ProtoOutputStream* protoOutput);
139 
140     // Computes the total byte size of all metrics managed by a single config source.
141     // Does not change the state.
142     virtual size_t byteSize();
143 
144     // Returns whether or not this config is active.
145     // The config is active if any metric in the config is active.
isActive()146     inline bool isActive() const {
147         return mIsActive;
148     }
149 
150     void loadActiveConfig(const ActiveConfig& config, int64_t currentTimeNs);
151 
152     void writeActiveConfigToProtoOutputStream(int64_t currentTimeNs, const DumpReportReason reason,
153                                               ProtoOutputStream* proto);
154 
155     // Returns true if at least one piece of metadata is written.
156     bool writeMetadataToProto(int64_t currentWallClockTimeNs, int64_t systemElapsedTimeNs,
157                               metadata::StatsMetadata* statsMetadata);
158 
159     void loadMetadata(const metadata::StatsMetadata& metadata, int64_t currentWallClockTimeNs,
160                       int64_t systemElapsedTimeNs);
161 
hasRestrictedMetricsDelegate()162     inline bool hasRestrictedMetricsDelegate() const {
163         return mRestrictedMetricsDelegatePackageName.has_value();
164     }
165 
getRestrictedMetricsDelegate()166     inline string getRestrictedMetricsDelegate() const {
167         return hasRestrictedMetricsDelegate() ? mRestrictedMetricsDelegatePackageName.value() : "";
168     }
169 
getConfigKey()170     inline ConfigKey getConfigKey() const {
171         return mConfigKey;
172     }
173 
174     void enforceRestrictedDataTtls(const int64_t wallClockNs);
175 
176     bool validateRestrictedMetricsDelegate(int32_t callingUid);
177 
178     virtual void flushRestrictedData();
179 
180     // Slow, should not be called in a hotpath.
181     vector<int64_t> getAllMetricIds() const;
182 
183     // Adds all atom ids referenced by matchers in the MetricsManager's config
184     void addAllAtomIds(LogEventFilter::AtomIdSet& allIds) const;
185 
186     // Gets the memory limit for the MetricsManager's config
getMaxMetricsBytes()187     inline size_t getMaxMetricsBytes() const {
188         return mMaxMetricsBytes;
189     }
190 
getTriggerGetDataBytes()191     inline size_t getTriggerGetDataBytes() const {
192         return mTriggerGetDataBytes;
193     }
194 
195 private:
196     // For test only.
getTtlEndNs()197     inline int64_t getTtlEndNs() const {
198         return mTtlEndNs;
199     }
200 
201     const ConfigKey mConfigKey;
202 
203     sp<UidMap> mUidMap;
204 
205     bool mHashStringsInReport = false;
206     bool mVersionStringsInReport = false;
207     bool mInstallerInReport = false;
208     uint8_t mPackageCertificateHashSizeBytes;
209 
210     int64_t mTtlNs;
211     int64_t mTtlEndNs;
212 
213     int64_t mLastReportTimeNs;
214     int64_t mLastReportWallClockNs;
215 
216     optional<InvalidConfigReason> mInvalidConfigReason;
217 
218     sp<StatsPullerManager> mPullerManager;
219 
220     // The uid log sources from StatsdConfig.
221     std::vector<int32_t> mAllowedUid;
222 
223     // The pkg log sources from StatsdConfig.
224     std::vector<std::string> mAllowedPkg;
225 
226     // The combined uid sources (after translating pkg name to uid).
227     // Logs from uids that are not in the list will be ignored to avoid spamming.
228     std::set<int32_t> mAllowedLogSources;
229 
230     // To guard access to mAllowedLogSources
231     mutable std::mutex mAllowedLogSourcesMutex;
232 
233     std::set<int32_t> mWhitelistedAtomIds;
234 
235     // We can pull any atom from these uids.
236     std::set<int32_t> mDefaultPullUids;
237 
238     // Uids that specific atoms can pull from.
239     // This is a map<atom id, set<uids>>
240     std::map<int32_t, std::set<int32_t>> mPullAtomUids;
241 
242     // Packages that specific atoms can be pulled from.
243     std::map<int32_t, std::set<std::string>> mPullAtomPackages;
244 
245     // All uids to pull for this atom. NOTE: Does not include the default uids for memory.
246     std::map<int32_t, std::set<int32_t>> mCombinedPullAtomUids;
247 
248     // Contains the annotations passed in with StatsdConfig.
249     std::list<std::pair<const int64_t, const int32_t>> mAnnotations;
250 
251     bool mShouldPersistHistory;
252     bool mUseV2SoftMemoryCalculation;
253 
254     bool mOmitSystemUidsInUidMap;
255     bool mOmitUnusedUidsInUidMap;
256     set<string> mAllowlistedUidMapPackages;
257 
258     // All event tags that are interesting to config metrics matchers.
259     std::unordered_map<int, std::vector<int>> mTagIdsToMatchersMap;
260 
261     // We only store the sp of AtomMatchingTracker, MetricProducer, and ConditionTracker in
262     // MetricsManager. There are relationships between them, and the relationships are denoted by
263     // index instead of pointers. The reasons for this are: (1) the relationship between them are
264     // complicated, so storing index instead of pointers reduces the risk that A holds B's sp, and B
265     // holds A's sp. (2) When we evaluate matcher results, or condition results, we can quickly get
266     // the related results from a cache using the index.
267 
268     // Hold all the atom matchers from the config.
269     std::vector<sp<AtomMatchingTracker>> mAllAtomMatchingTrackers;
270 
271     // Hold all the conditions from the config.
272     std::vector<sp<ConditionTracker>> mAllConditionTrackers;
273 
274     // Hold all metrics from the config.
275     std::vector<sp<MetricProducer>> mAllMetricProducers;
276 
277     // Hold all alert trackers.
278     std::vector<sp<AnomalyTracker>> mAllAnomalyTrackers;
279 
280     // Hold all periodic alarm trackers.
281     std::vector<sp<AlarmTracker>> mAllPeriodicAlarmTrackers;
282 
283     // To make updating configs faster, we map the id of a AtomMatchingTracker, MetricProducer, and
284     // ConditionTracker to its index in the corresponding vector.
285 
286     // Maps the id of an atom matching tracker to its index in mAllAtomMatchingTrackers.
287     std::unordered_map<int64_t, int> mAtomMatchingTrackerMap;
288 
289     // Maps the id of a condition tracker to its index in mAllConditionTrackers.
290     std::unordered_map<int64_t, int> mConditionTrackerMap;
291 
292     // Maps the id of a metric producer to its index in mAllMetricProducers.
293     std::unordered_map<int64_t, int> mMetricProducerMap;
294 
295     // To make the log processing more efficient, we want to do as much filtering as possible
296     // before we go into individual trackers and conditions to match.
297 
298     // 1st filter: check if the event tag id is in mTagIdsToMatchersMap.
299     // 2nd filter: if it is, we parse the event because there is at least one member is interested.
300     //             then pass to all AtomMatchingTrackers (itself also filter events by ids).
301     // 3nd filter: for AtomMatchingTrackers that matched this event, we pass this event to the
302     //             ConditionTrackers and MetricProducers that use this matcher.
303     // 4th filter: for ConditionTrackers that changed value due to this event, we pass
304     //             new conditions to  metrics that use this condition.
305 
306     // The following map is initialized from the statsd_config.
307 
308     // Maps from the index of the AtomMatchingTracker to index of MetricProducer.
309     std::unordered_map<int, std::vector<int>> mTrackerToMetricMap;
310 
311     // Maps from AtomMatchingTracker to ConditionTracker
312     std::unordered_map<int, std::vector<int>> mTrackerToConditionMap;
313 
314     // Maps from ConditionTracker to MetricProducer
315     std::unordered_map<int, std::vector<int>> mConditionToMetricMap;
316 
317     // Maps from life span triggering event to MetricProducers.
318     std::unordered_map<int, std::vector<int>> mActivationAtomTrackerToMetricMap;
319 
320     // Maps deactivation triggering event to MetricProducers.
321     std::unordered_map<int, std::vector<int>> mDeactivationAtomTrackerToMetricMap;
322 
323     // Maps AlertIds to the index of the corresponding AnomalyTracker stored in mAllAnomalyTrackers.
324     // The map is used in LoadMetadata to more efficiently lookup AnomalyTrackers from an AlertId.
325     std::unordered_map<int64_t, int> mAlertTrackerMap;
326 
327     std::vector<int> mMetricIndexesWithActivation;
328 
checkLogCredentials(const LogEvent & event)329     inline bool checkLogCredentials(const LogEvent& event) const {
330         return checkLogCredentials(event.GetUid(), event.GetTagId());
331     }
332 
333     bool checkLogCredentials(int32_t uid, int32_t atomId) const;
334 
335     void initAllowedLogSources();
336 
337     void initPullAtomSources();
338 
339     // Only called on config creation/update to initialize log sources from the config.
340     // Calls initAllowedLogSources and initPullAtomSources. Sets up mInvalidConfigReason on
341     // error.
342     void createAllLogSourcesFromConfig(const StatsdConfig& config);
343 
344     // Verifies the config meets guardrails and updates statsdStats.
345     // Sets up mInvalidConfigReason on error. Should be called on config creation/update
346     void verifyGuardrailsAndUpdateStatsdStats();
347 
348     // Initializes mIsAlwaysActive and mIsActive.
349     // Should be called on config creation/update.
350     void initializeConfigActiveStatus();
351 
352     // The metrics that don't need to be uploaded or even reported.
353     std::set<int64_t> mNoReportMetricIds;
354 
355     // The config is active if any metric in the config is active.
356     bool mIsActive;
357 
358     // The config is always active if any metric in the config does not have an activation signal.
359     bool mIsAlwaysActive;
360 
361     // Hashes of the States used in this config, keyed by the state id, used in config updates.
362     std::map<int64_t, uint64_t> mStateProtoHashes;
363 
364     // Optional package name of the delegate that processes restricted metrics
365     // If set, restricted metrics are only uploaded to the delegate.
366     optional<string> mRestrictedMetricsDelegatePackageName = nullopt;
367 
368     // Only called on config creation/update. Sets the memory limit in bytes for storing metrics.
369     void setMaxMetricsBytesFromConfig(const StatsdConfig& config);
370 
371     // Only called on config creation/update. Sets the soft memory limit in bytes for storing
372     // metrics.
373     void setTriggerGetDataBytesFromConfig(const StatsdConfig& config);
374 
375     // Parse SocketLossInfo and propagate info to the metrics
376     void onLogEventLost(const SocketLossInfo& socketLossInfo);
377 
378     /**
379      * @brief Update metrics depending on #lostAtomId that it was lost due to #reason
380      * @return number of notified metrics
381      */
382     int notifyMetricsAboutLostAtom(int32_t lostAtomId, DataCorruptedReason reason);
383 
384     /**
385      * Updates MetricProducers with DataCorruptionReason due to queue overflow atom loss
386      * Notifies metrics only when new queue overflow happens since previous request
387      * Performs QueueOverflowAtomsStatsMap tracking via managing stats local copy
388      * The assumption is that QueueOverflowAtomsStatsMap collected over time, and that none
389      * of atom id counters have disappeared (which is StatsdStats logic until it explicitly reset,
390      * which should not be happen during statsd service lifetime)
391      */
392     void processQueueOverflowStats();
393 
394     // The memory limit in bytes for storing metrics
395     size_t mMaxMetricsBytes;
396 
397     // The memory limit in bytes for triggering get data.
398     size_t mTriggerGetDataBytes;
399 
400     // Dropped atoms stats due to queue overflow observed up to latest dumpReport request
401     // this map is not cleared during onDumpReport to preserve tracking information and avoid
402     // repeated metric notification about past queue overflow lost event
403     // This map represent local copy of StatsdStats::mPushedAtomDropsStats with relevant atoms ids
404     StatsdStats::QueueOverflowAtomsStatsMap mQueueOverflowAtomsStats;
405 
406     friend class SocketLossInfoTest;
407     FRIEND_TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks);
408     FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid);
409     FRIEND_TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain);
410 
411     FRIEND_TEST(GaugeMetricE2ePushedTest, TestDimensionalSampling);
412     FRIEND_TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTrigger);
413     FRIEND_TEST(GaugeMetricE2ePulledTest, TestFirstNSamplesPulledNoTriggerWithActivation);
414     FRIEND_TEST(GaugeMetricE2ePushedTest, TestMultipleFieldsForPushedEvent);
415     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvents);
416     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEvent_LateAlarm);
417     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsWithActivation);
418     FRIEND_TEST(GaugeMetricE2ePulledTest, TestRandomSamplePulledEventsNoCondition);
419     FRIEND_TEST(GaugeMetricE2ePulledTest, TestConditionChangeToTrueSamplePulledEvents);
420 
421     FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_single_bucket);
422     FRIEND_TEST(AnomalyCountDetectionE2eTest, TestSlicedCountMetric_multiple_buckets);
423     FRIEND_TEST(AnomalyCountDetectionE2eTest,
424                 TestCountMetric_save_refractory_to_disk_no_data_written);
425     FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_save_refractory_to_disk);
426     FRIEND_TEST(AnomalyCountDetectionE2eTest, TestCountMetric_load_refractory_from_disk);
427     FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
428     FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_partial_bucket);
429     FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
430     FRIEND_TEST(AnomalyDurationDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
431 
432     FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
433     FRIEND_TEST(ConfigTtlE2eTest, TestCountMetric);
434     FRIEND_TEST(ConfigUpdateE2eAbTest, TestConfigTtl);
435     FRIEND_TEST(MetricActivationE2eTest, TestCountMetric);
436     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation);
437     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations);
438     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation);
439     FRIEND_TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations);
440 
441     FRIEND_TEST(MetricsManagerTest, TestLogSources);
442     FRIEND_TEST(MetricsManagerTest, TestCheckLogCredentialsWhitelistedAtom);
443     FRIEND_TEST(MetricsManagerTest, TestLogSourcesOnConfigUpdate);
444     FRIEND_TEST(MetricsManagerTest_SPlus, TestRestrictedMetricsConfig);
445     FRIEND_TEST(MetricsManagerTest_SPlus, TestRestrictedMetricsConfigUpdate);
446     FRIEND_TEST(MetricsManagerUtilTest, TestSampledMetrics);
447     FRIEND_TEST(MetricsManagerUtilTest, TestUidFields);
448 
449     FRIEND_TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead);
450     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBoot);
451     FRIEND_TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations);
452     FRIEND_TEST(StatsLogProcessorTest,
453                 TestActivationOnBootMultipleActivationsDifferentActivationTypes);
454     FRIEND_TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart);
455 
456     FRIEND_TEST(CountMetricE2eTest, TestInitialConditionChanges);
457     FRIEND_TEST(CountMetricE2eTest, TestSlicedState);
458     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithMap);
459     FRIEND_TEST(CountMetricE2eTest, TestMultipleSlicedStates);
460     FRIEND_TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields);
461 
462     FRIEND_TEST(DurationMetricE2eTest, TestOneBucket);
463     FRIEND_TEST(DurationMetricE2eTest, TestTwoBuckets);
464     FRIEND_TEST(DurationMetricE2eTest, TestWithActivation);
465     FRIEND_TEST(DurationMetricE2eTest, TestWithCondition);
466     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedCondition);
467     FRIEND_TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition);
468     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedState);
469     FRIEND_TEST(DurationMetricE2eTest, TestWithConditionAndSlicedState);
470     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStateMapped);
471     FRIEND_TEST(DurationMetricE2eTest, TestWithSlicedStatePrimaryFieldsSubset);
472     FRIEND_TEST(DurationMetricE2eTest, TestUploadThreshold);
473 
474     FRIEND_TEST(ValueMetricE2eTest, TestInitialConditionChanges);
475     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents);
476     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm);
477     FRIEND_TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation);
478     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState);
479     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithDimensions);
480     FRIEND_TEST(ValueMetricE2eTest, TestInitWithSlicedState_WithIncorrectDimensions);
481     FRIEND_TEST(ValueMetricE2eTest, TestInitWithMultipleAggTypes);
482     FRIEND_TEST(ValueMetricE2eTest, TestInitWithDefaultAggType);
483 
484     FRIEND_TEST(DataCorruptionQueueOverflowTest, TestNotifyOnlyInterestedMetrics);
485     FRIEND_TEST(DataCorruptionQueueOverflowTest, TestNotifyInterestedMetricsWithNewLoss);
486     FRIEND_TEST(DataCorruptionQueueOverflowTest, TestDoNotNotifyInterestedMetricsIfNoUpdate);
487     FRIEND_TEST(DataCorruptionQueueOverflowTest, TestDoNotNotifyNewInterestedMetricsIfNoUpdate);
488 };
489 
490 }  // namespace statsd
491 }  // namespace os
492 }  // namespace android
493