Add ScopedThreadSuspension

Fixes the TransitionFromRunnableToSuspended and
TransitionFromSuspendedToRunnable pattern that was prone to errors.

Change-Id: Ie6ae9c0357c83b4fc4899d05dfa0975553170267
diff --git a/runtime/native/dalvik_system_VMStack.cc b/runtime/native/dalvik_system_VMStack.cc
index 541eeb1..7910f94 100644
--- a/runtime/native/dalvik_system_VMStack.cc
+++ b/runtime/native/dalvik_system_VMStack.cc
@@ -35,15 +35,16 @@
     trace = soa.Self()->CreateInternalStackTrace<false>(soa);
   } else {
     // Suspend thread to build stack trace.
-    soa.Self()->TransitionFromRunnableToSuspended(kNative);
+    ScopedThreadSuspension sts(soa.Self(), kSuspended);
     ThreadList* thread_list = Runtime::Current()->GetThreadList();
     bool timed_out;
     Thread* thread = thread_list->SuspendThreadByPeer(peer, true, false, &timed_out);
     if (thread != nullptr) {
       // Must be runnable to create returned array.
-      CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kNative);
-      trace = thread->CreateInternalStackTrace<false>(soa);
-      soa.Self()->TransitionFromRunnableToSuspended(kNative);
+      {
+        ScopedObjectAccess soa2(soa.Self());
+        trace = thread->CreateInternalStackTrace<false>(soa);
+      }
       // Restart suspended thread.
       thread_list->Resume(thread, false);
     } else {
@@ -52,7 +53,6 @@
             "generous timeout.";
       }
     }
-    CHECK_EQ(soa.Self()->TransitionFromSuspendedToRunnable(), kNative);
   }
   return trace;
 }