Add ScopedSilentDeath to libbase

ScopedSilentDeath can be used to supress debuggerd stack traces on a
per-test basis, whereas SilentDeathTest requires creation of a new test
fixture.

Since the realtime stability system works by looking at native stack
traces, crashes from death tests can be picked up as something
unexpected. We can use ScopedSilentDeath or SilentDeathTest to prevent
this from happening.

Bug: 212662036
Test: build
Change-Id: I0b92129d4935e87de32abc410bfa979f514a80fb
diff --git a/include/android-base/silent_death_test.h b/include/android-base/silent_death_test.h
index 2aec890..16f99ef 100644
--- a/include/android-base/silent_death_test.h
+++ b/include/android-base/silent_death_test.h
@@ -17,34 +17,70 @@
 #pragma once
 
 #include <signal.h>
-
 #include <gtest/gtest.h>
 
+#include <array>
+#include <memory>
+
 #if !defined(__BIONIC__)
 #define sigaction64 sigaction
 #endif
 
-// Disables debuggerd stack traces to speed up death tests and make them less
-// noisy in logcat.
+// Disables debuggerd stack traces to speed up death tests, make them less
+// noisy in logcat, and avoid expected deaths from showing up in stability metrics.
 //
-// Use `using my_DeathTest = SilentDeathTest;` instead of inheriting from
-// testing::Test yourself.
-class SilentDeathTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    // Suppress debuggerd stack traces. Too slow.
-    for (int signo : {SIGABRT, SIGBUS, SIGSEGV, SIGSYS}) {
+// When writing new death tests, inherit the test suite from SilentDeathTest
+// defined below. Only use ScopedSilentDeath in a test case/suite if changing the
+// test base from testing::Test to SilentDeathTest adds additional complextity when
+// test suite code is shared between death and non-death tests.
+//
+// For example, use ScopedSilentDeath if you have:
+//   class FooTest : public testing::Test { ... /* shared setup/teardown */ };
+//
+//   using FooDeathTest = FooTest;
+//
+//   TEST_F(FooTest, DoesThis) {
+//     // normal test
+//   }
+//
+//   TEST_F (FooDeathTest, DoesThat) {
+//     ScopedSilentDeath _silentDeath;
+//     // death test
+//   }
+class ScopedSilentDeath {
+ public:
+  ScopedSilentDeath() {
+    for (int signo : SUPPRESSED_SIGNALS) {
       struct sigaction64 action = {.sa_handler = SIG_DFL};
       sigaction64(signo, &action, &previous_);
     }
   }
 
-  virtual void TearDown() {
-    for (int signo : {SIGABRT, SIGBUS, SIGSEGV, SIGSYS}) {
+  ~ScopedSilentDeath() {
+    for (int signo : SUPPRESSED_SIGNALS) {
       sigaction64(signo, &previous_, nullptr);
     }
   }
 
  private:
+  static constexpr std::array<int, 4> SUPPRESSED_SIGNALS = {SIGABRT, SIGBUS, SIGSEGV, SIGSYS};
+
   struct sigaction64 previous_;
 };
+
+// When writing death tests, use `using myDeathTest = SilentDeathTest;` or inherit from
+// SilentDeathTest instead of inheriting from testing::Test yourself.
+//
+// Disables debuggerd stack traces to speed up death tests, make them less
+// noisy in logcat, and avoid expected deaths from showing up in stability metrics.
+class SilentDeathTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    silent_death_ = std::unique_ptr<ScopedSilentDeath>(new ScopedSilentDeath);
+  }
+
+  void TearDown() override { silent_death_.reset(); }
+
+ private:
+  std::unique_ptr<ScopedSilentDeath> silent_death_;
+};