Merge "Timestamp Truncating whitelist."
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 2585aa3..fddfd93 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -129,12 +129,23 @@
 
     long long wrapperToken =
             mProto->start(FIELD_TYPE_MESSAGE | FIELD_COUNT_REPEATED | FIELD_ID_DATA);
-    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
-        (long long)event.GetElapsedTimestampNs());
+
     long long eventToken = mProto->start(FIELD_TYPE_MESSAGE | FIELD_ID_ATOMS);
+    const bool truncateTimestamp =
+        android::util::kNotTruncatingTimestampAtomWhiteList.find(event.GetTagId()) ==
+        android::util::kNotTruncatingTimestampAtomWhiteList.end();
+    if (truncateTimestamp) {
+        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
+            (long long)truncateTimestampNsToFiveMinutes(event.GetElapsedTimestampNs()));
+        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
+            (long long)truncateTimestampNsToFiveMinutes(getWallClockNs()));
+    } else {
+        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_ELAPSED_TIMESTAMP_NANOS,
+            (long long)event.GetElapsedTimestampNs());
+        mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
+            (long long)getWallClockNs());
+    }
     event.ToProto(*mProto);
-    mProto->write(FIELD_TYPE_INT64 | FIELD_ID_WALL_CLOCK_TIMESTAMP_NANOS,
-        (long long)getWallClockNs());
     mProto->end(eventToken);
     mProto->end(wrapperToken);
 }
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 0daa506..7d09ff9 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -173,11 +173,15 @@
                     writeFieldValueTreeToStream(mTagId, *(atom.mFields), protoOutput);
                 }
                 protoOutput->end(atomsToken);
-
                 for (const auto& atom : bucket.mGaugeAtoms) {
+                    const bool truncateTimestamp =
+                        android::util::kNotTruncatingTimestampAtomWhiteList.find(mTagId) ==
+                        android::util::kNotTruncatingTimestampAtomWhiteList.end();
+                    int64_t timestampNs =  truncateTimestamp ?
+                        truncateTimestampNsToFiveMinutes(atom.mTimestamps) : atom.mTimestamps;
                     protoOutput->write(
                         FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_ELAPSED_ATOM_TIMESTAMP,
-                        (long long)atom.mTimestamps);
+                        (long long)timestampNs);
                 }
             }
             protoOutput->end(bucketInfoToken);
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 30eef4f..2c7b919 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -290,6 +290,10 @@
     return time(nullptr) * MS_PER_SEC;
 }
 
+int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs) {
+    return timestampNs / NS_PER_SEC / (5 * 60) * NS_PER_SEC * (5 * 60);
+}
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/src/stats_log_util.h b/cmds/statsd/src/stats_log_util.h
index 6a5123d..5922642 100644
--- a/cmds/statsd/src/stats_log_util.h
+++ b/cmds/statsd/src/stats_log_util.h
@@ -73,6 +73,9 @@
     return message->ParseFromArray(pbBytes.c_str(), pbBytes.size());
 }
 
+// Returns the truncated timestamp.
+int64_t truncateTimestampNsToFiveMinutes(int64_t timestampNs);
+
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index f0628c0..a50fd16 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -365,6 +365,18 @@
     fprintf(out, "};\n");
     fprintf(out, "\n");
 
+    std::set<string> kFuzzingAtomNames = { "mobile_radio_power_state_changed" };
+    fprintf(out, "const static std::set<int> kNotTruncatingTimestampAtomWhiteList = {\n");
+    for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
+        atom != atoms.decls.end(); atom++) {
+        if (kFuzzingAtomNames.find(atom->name) == kFuzzingAtomNames.end()) {
+            string constant = make_constant_name(atom->name);
+            fprintf(out, " %s,\n", constant.c_str());
+        }
+    }
+    fprintf(out, "};\n");
+    fprintf(out, "\n");
+
     fprintf(out, "const static std::set<int> kAtomsWithUidField = {\n");
     for (set<AtomDecl>::const_iterator atom = atoms.decls.begin();
         atom != atoms.decls.end(); atom++) {