Statsd: Add watchdog rollback to experiment ids

Stores experiment ids to disk for watchdog rollback initiate/success
events as discussed.

Test: gts in topic
Bug: 131768455
Change-Id: I32768fe5c5c21c43811e25d8f87faae0c8d82c1f
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 8191d37..bbd3dca 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1264,7 +1264,7 @@
     // This method only sends data, it does not receive it.
     pid_t pid = IPCThreadState::self()->getCallingPid();
     uid_t uid = IPCThreadState::self()->getCallingUid();
-        // Root, system, and shell always have access
+    // Root, system, and shell always have access
     if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
         // Caller must be granted these permissions
         if (!checkCallingPermission(String16(kPermissionDump))) {
@@ -1349,6 +1349,64 @@
     return Status::ok();
 }
 
+Status StatsService::sendWatchdogRollbackOccurredAtom(const int32_t rollbackTypeIn,
+                                                      const android::String16& packageNameIn,
+                                                      const int64_t packageVersionCodeIn) {
+    // Note: We skip the usage stats op check here since we do not have a package name.
+    // This is ok since we are overloading the usage_stats permission.
+    // This method only sends data, it does not receive it.
+    pid_t pid = IPCThreadState::self()->getCallingPid();
+    uid_t uid = IPCThreadState::self()->getCallingUid();
+    // Root, system, and shell always have access
+    if (uid != AID_ROOT && uid != AID_SYSTEM && uid != AID_SHELL) {
+        // Caller must be granted these permissions
+        if (!checkCallingPermission(String16(kPermissionDump))) {
+            return exception(binder::Status::EX_SECURITY,
+                             StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+                                          kPermissionDump));
+        }
+        if (!checkCallingPermission(String16(kPermissionUsage))) {
+            return exception(binder::Status::EX_SECURITY,
+                             StringPrintf("UID %d / PID %d lacks permission %s", uid, pid,
+                                          kPermissionUsage));
+        }
+    }
+
+    android::util::stats_write(android::util::WATCHDOG_ROLLBACK_OCCURRED,
+            rollbackTypeIn, String8(packageNameIn).string(), packageVersionCodeIn);
+
+    // Fast return to save disk read.
+    if (rollbackTypeIn != android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS
+            && rollbackTypeIn !=
+                    android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE) {
+        return Status::ok();
+    }
+
+    bool readTrainInfoSuccess = false;
+    InstallTrainInfo trainInfoOnDisk;
+    readTrainInfoSuccess = StorageManager::readTrainInfo(trainInfoOnDisk);
+
+    if (!readTrainInfoSuccess) {
+        return Status::ok();
+    }
+    std::vector<int64_t> experimentIds = trainInfoOnDisk.experimentIds;
+    if (experimentIds.empty()) {
+        return Status::ok();
+    }
+    switch (rollbackTypeIn) {
+        case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_INITIATE:
+            experimentIds.push_back(experimentIds[0] + 4);
+            break;
+        case android::util::WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS:
+            experimentIds.push_back(experimentIds[0] + 5);
+            break;
+    }
+    StorageManager::writeTrainInfo(trainInfoOnDisk.trainVersionCode, trainInfoOnDisk.trainName,
+            trainInfoOnDisk.status, experimentIds);
+    return Status::ok();
+}
+
+
 Status StatsService::getRegisteredExperimentIds(std::vector<int64_t>* experimentIdsOut) {
     uid_t uid = IPCThreadState::self()->getCallingUid();
 
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index a4e6d7f..8d8514f 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -196,6 +196,14 @@
             const std::vector<int64_t>& experimentIdsIn) override;
 
     /**
+     * Binder call to log WatchdogRollbackOccurred atom.
+     */
+    virtual Status sendWatchdogRollbackOccurredAtom(
+            const int32_t rollbackTypeIn,
+            const android::String16& packageNameIn,
+            const int64_t packageVersionCodeIn) override;
+
+    /**
      * Binder call to get registered experiment IDs.
      */
     virtual Status getRegisteredExperimentIds(std::vector<int64_t>* expIdsOut);