Merge "libpower: try detect memory corruption and abort"
diff --git a/power.cpp b/power.cpp
index c4f2036..093fd4c 100644
--- a/power.cpp
+++ b/power.cpp
@@ -18,6 +18,7 @@
 #define ATRACE_TAG ATRACE_TAG_POWER
 
 #include <android-base/logging.h>
+#include <android/system/suspend/1.0/BpHwSystemSuspend.h>
 #include <android/system/suspend/1.0/ISystemSuspend.h>
 #include <hardware_legacy/power.h>
 #include <utils/Trace.h>
@@ -36,7 +37,30 @@
 static std::unordered_map<std::string, sp<IWakeLock>> gWakeLockMap;
 
 static const sp<ISystemSuspend>& getSystemSuspendServiceOnce() {
-    static sp<ISystemSuspend> suspendService = ISystemSuspend::getService();
+    using android::system::suspend::V1_0::BpHwSystemSuspend;
+    static std::once_flag initFlag;
+    static sp<ISystemSuspend> suspendService = nullptr;
+
+    // TODO(b/117575503): We use this buffer to make sure that suspendService pointer and the
+    // underlying memory are not corrupted before using it. Ideally, memory corruption should be
+    // fixed.
+    static constexpr size_t bufSize = sizeof(BpHwSystemSuspend);
+    static char buf[bufSize];
+
+    std::call_once(initFlag, []() {
+        // It's possible for the calling process to not have permissions to
+        // ISystemSuspend. getService will then return nullptr.
+        suspendService = ISystemSuspend::getService();
+        if (suspendService) {
+            std::memcpy(buf, static_cast<void*>(suspendService.get()), bufSize);
+        }
+    });
+    if (suspendService) {
+        if (std::memcmp(buf, static_cast<void*>(suspendService.get()), bufSize) != 0) {
+            LOG(FATAL) << "Memory corrupted. Aborting.";
+        }
+    }
+
     return suspendService;
 }