TrainInfo persist onto disk

+ TrainInfo puller

Bug: 122807604
Test: will add gts
Change-Id: Iac9576ba0edc235dc117950f92bc7d7a8ad75ca8
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 04ab592..f408655 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -76,6 +76,7 @@
         "src/external/SubsystemSleepStatePuller.cpp",
         "src/external/PowerStatsPuller.cpp",
         "src/external/ResourceHealthManagerPuller.cpp",
+        "src/external/TrainInfoPuller.cpp",
         "src/external/StatsPullerManager.cpp",
         "src/external/puller_util.cpp",
         "src/logd/LogEvent.cpp",
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index d23fc62..fb603b9 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -55,9 +55,6 @@
 namespace os {
 namespace statsd {
 
-const int FIELD_ID_EXPERIMENT_ID = 1;
-const int FIELD_ID_EXPERIMENT_ID_MSG = 7;
-
 constexpr const char* kPermissionDump = "android.permission.DUMP";
 constexpr const char* kPermissionUsage = "android.permission.PACKAGE_USAGE_STATS";
 
@@ -67,6 +64,8 @@
 
 // for StatsDataDumpProto
 const int FIELD_ID_REPORTS_LIST = 1;
+// for TrainInfo experiment id serialization
+const int FIELD_ID_EXPERIMENT_ID = 1;
 
 static binder::Status ok() {
     return binder::Status::ok();
@@ -1200,12 +1199,10 @@
     bool requiresLowLatencyMonitor = options | IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
 
     ProtoOutputStream proto;
-    uint64_t protoToken = proto.start(FIELD_TYPE_MESSAGE | FIELD_ID_EXPERIMENT_ID_MSG);
     for (const auto& expId : experimentIds) {
         proto.write(FIELD_TYPE_INT64 | FIELD_COUNT_REPEATED | FIELD_ID_EXPERIMENT_ID,
                     (long long)expId);
     }
-    proto.end(protoToken);
 
     vector<uint8_t> buffer;
     buffer.resize(proto.size());
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index ed72b29..98f810f 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -29,10 +29,11 @@
 #include "../statscompanion_util.h"
 #include "PowerStatsPuller.h"
 #include "ResourceHealthManagerPuller.h"
-#include "StatsCompanionServicePuller.h"
 #include "StatsCallbackPuller.h"
+#include "StatsCompanionServicePuller.h"
 #include "StatsPullerManager.h"
 #include "SubsystemSleepStatePuller.h"
+#include "TrainInfoPuller.h"
 #include "statslog.h"
 
 #include <iostream>
@@ -152,7 +153,7 @@
                   new StatsCompanionServicePuller(android::util::PROCESS_MEMORY_HIGH_WATER_MARK)}},
         // temperature
         {android::util::TEMPERATURE,
-          {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
+         {.puller = new StatsCompanionServicePuller(android::util::TEMPERATURE)}},
         // binder_calls
         {android::util::BINDER_CALLS,
          {.additiveFields = {4, 5, 6, 8, 12},
@@ -231,6 +232,8 @@
         // PermissionState.
         {android::util::DANGEROUS_PERMISSION_STATE,
          {.puller = new StatsCompanionServicePuller(android::util::DANGEROUS_PERMISSION_STATE)}},
+        // TrainInfo.
+        {android::util::TRAIN_INFO, {.puller = new TrainInfoPuller()}},
 };
 
 StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/cmds/statsd/src/external/TrainInfoPuller.cpp b/cmds/statsd/src/external/TrainInfoPuller.cpp
new file mode 100644
index 0000000..9d09242
--- /dev/null
+++ b/cmds/statsd/src/external/TrainInfoPuller.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define DEBUG false  // STOPSHIP if true
+#include "Log.h"
+
+#include "external/StatsPuller.h"
+
+#include "TrainInfoPuller.h"
+#include "logd/LogEvent.h"
+#include "stats_log_util.h"
+#include "statslog.h"
+#include "storage/StorageManager.h"
+
+using std::make_shared;
+using std::shared_ptr;
+
+namespace android {
+namespace os {
+namespace statsd {
+
+TrainInfoPuller::TrainInfoPuller() :
+    StatsPuller(android::util::TRAIN_INFO) {
+}
+
+bool TrainInfoPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
+    InstallTrainInfo trainInfo;
+    bool ret = StorageManager::readTrainInfo(trainInfo);
+    if (!ret) {
+        ALOGW("Failed to read train info.");
+        return false;
+    }
+    auto event = make_shared<LogEvent>(getWallClockNs(), getElapsedRealtimeNs(), trainInfo);
+    data->push_back(event);
+    return true;
+}
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/external/TrainInfoPuller.h b/cmds/statsd/src/external/TrainInfoPuller.h
new file mode 100644
index 0000000..615d023
--- /dev/null
+++ b/cmds/statsd/src/external/TrainInfoPuller.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "StatsPuller.h"
+
+namespace android {
+namespace os {
+namespace statsd {
+
+/**
+ * Reads train info from disk.
+ */
+class TrainInfoPuller : public StatsPuller {
+ public:
+  TrainInfoPuller();
+
+ private:
+  bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
+};
+
+}  // namespace statsd
+}  // namespace os
+}  // namespace android
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 99ebc96..dec36b5 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -361,6 +361,16 @@
     }
 }
 
+LogEvent::LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                   const InstallTrainInfo& trainInfo) {
+    mLogdTimestampNs = wallClockTimestampNs;
+    mElapsedTimestampNs = elapsedTimestampNs;
+    mTagId = android::util::TRAIN_INFO;
+    mValues.push_back(
+            FieldValue(Field(mTagId, getSimpleField(1)), Value(trainInfo.trainVersionCode)));
+    mValues.push_back(FieldValue(Field(mTagId, getSimpleField(2)), Value(trainInfo.experimentIds)));
+}
+
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs) : LogEvent(tagId, timestampNs, 0) {}
 
 LogEvent::LogEvent(int32_t tagId, int64_t timestampNs, int32_t uid) {
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 6b5fa56..111a619 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -55,6 +55,11 @@
     int32_t mUid;
     std::string mTag;
 };
+
+struct InstallTrainInfo {
+    int64_t trainVersionCode;
+    std::vector<uint8_t> experimentIds;
+};
 /**
  * Wrapper for the log_msg structure.
  */
@@ -132,6 +137,9 @@
     explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
                       const VendorAtom& vendorAtom);
 
+    explicit LogEvent(int64_t wallClockTimestampNs, int64_t elapsedTimestampNs,
+                      const InstallTrainInfo& installTrainInfo);
+
     ~LogEvent();
 
     /**
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index fe465ce..165e57c 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -127,7 +127,7 @@
     return true;
 }
 
-bool StorageManager::readTrainInfo(TrainInfo& trainInfo) {
+bool StorageManager::readTrainInfo(InstallTrainInfo& trainInfo) {
     std::lock_guard<std::mutex> lock(sTrainInfoMutex);
 
     unique_ptr<DIR, decltype(&closedir)> dir(opendir(TRAIN_INFO_DIR), closedir);
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index d9eca9f..d6df867 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -49,7 +49,7 @@
     /**
      * Reads train info.
      */
-    static bool readTrainInfo(TrainInfo& trainInfo);
+    static bool readTrainInfo(InstallTrainInfo& trainInfo);
 
     /**
      * Reads the file content to the buffer.
diff --git a/cmds/statsd/tests/storage/StorageManager_test.cpp b/cmds/statsd/tests/storage/StorageManager_test.cpp
index ce957a3..f66de05 100644
--- a/cmds/statsd/tests/storage/StorageManager_test.cpp
+++ b/cmds/statsd/tests/storage/StorageManager_test.cpp
@@ -30,14 +30,14 @@
 using testing::Contains;
 
 TEST(StorageManagerTest, TrainInfoReadWriteTest) {
-    TrainInfo trainInfo;
+    InstallTrainInfo trainInfo;
     trainInfo.trainVersionCode = 12345;
     const char* expIds = "test_ids";
     trainInfo.experimentIds.assign(expIds, expIds + strlen(expIds));
 
     StorageManager::writeTrainInfo(trainInfo.trainVersionCode, trainInfo.experimentIds);
 
-    TrainInfo result;
+    InstallTrainInfo result;
     StorageManager::readTrainInfo(result);
     EXPECT_EQ(trainInfo.trainVersionCode, result.trainVersionCode);
     EXPECT_EQ(trainInfo.experimentIds.size(), result.experimentIds.size());