Merge "Persist data to disk when system shuts down" into pi-dev
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index b175b3c..9ed4ed0 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -40,7 +40,8 @@
     GET_DATA_CALLED = 4,
     ADB_DUMP = 5,
     CONFIG_RESET = 6,
-    STATSCOMPANION_DIED = 7
+    STATSCOMPANION_DIED = 7,
+    TERMINATION_SIGNAL_RECEIVED = 8
 };
 
 class StatsLogProcessor : public ConfigListener {
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 10c04f6..cb48a71 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -881,6 +881,13 @@
     mConfigManager->Startup();
 }
 
+void StatsService::Terminate() {
+    ALOGI("StatsService::Terminating");
+    if (mProcessor != nullptr) {
+        mProcessor->WriteDataToDisk(TERMINATION_SIGNAL_RECEIVED);
+    }
+}
+
 void StatsService::OnLogEvent(LogEvent* event, bool reconnectionStarts) {
     mProcessor->OnLogEvent(event, reconnectionStarts);
 }
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index b3a4776..d8aab88 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -74,6 +74,11 @@
     void Startup();
 
     /**
+     * Called when terminiation signal received.
+     */
+    void Terminate();
+
+    /**
      * Called by LogReader when there's a log event to process.
      */
     virtual void OnLogEvent(LogEvent* event, bool reconnectionStarts);
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index e8904c6..58bbd96 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -96,6 +96,27 @@
     return NO_ERROR;
 }
 
+
+sp<StatsService> gStatsService = nullptr;
+
+void sigHandler(int sig) {
+    if (gStatsService != nullptr) {
+        gStatsService->Terminate();
+    }
+}
+
+void registerSigHandler()
+{
+    struct sigaction sa;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = sigHandler;
+    sigaction(SIGHUP, &sa, nullptr);
+    sigaction(SIGINT, &sa, nullptr);
+    sigaction(SIGQUIT, &sa, nullptr);
+    sigaction(SIGTERM, &sa, nullptr);
+}
+
 int main(int /*argc*/, char** /*argv*/) {
     // Set up the looper
     sp<Looper> looper(Looper::prepare(0 /* opts */));
@@ -108,21 +129,24 @@
     IPCThreadState::self()->disableBackgroundScheduling(true);
 
     // Create the service
-    sp<StatsService> service = new StatsService(looper);
-    if (defaultServiceManager()->addService(String16("stats"), service) != 0) {
+    gStatsService = new StatsService(looper);
+    if (defaultServiceManager()->addService(String16("stats"), gStatsService) != 0) {
         ALOGE("Failed to add service");
         return -1;
     }
-    service->sayHiToStatsCompanion();
 
-    service->Startup();
+    registerSigHandler();
 
-    sp<StatsSocketListener> socketListener = new StatsSocketListener(service);
+    gStatsService->sayHiToStatsCompanion();
+
+    gStatsService->Startup();
+
+    sp<StatsSocketListener> socketListener = new StatsSocketListener(gStatsService);
 
     if (kUseLogd) {
         ALOGI("using logd");
         // Start the log reader thread
-        status_t err = start_log_reader_thread(service);
+        status_t err = start_log_reader_thread(gStatsService);
         if (err != NO_ERROR) {
             return 1;
         }
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index 2fe17da..1c70d88 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -265,6 +265,7 @@
       ADB_DUMP = 5;
       CONFIG_RESET = 6;
       STATSCOMPANION_DIED = 7;
+      TERMINATION_SIGNAL_RECEIVED = 8;
   }
   optional DumpReportReason dump_report_reason = 8;