Parcel: better debug recycle

Detect recycle called twice always (and when DEBUG_RECYCLE is on, we
detect recycle called twice or called zero times, and we show a stack).

Bug: 231799394
Test: manual (calling recycle twice)
Change-Id: I1dd9f392ee916edd9c598085a1c19dbdd3ce957f
Merged-In: I1dd9f392ee916edd9c598085a1c19dbdd3ce957f
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6411f42..40e6780 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -247,6 +247,7 @@
     private ArrayMap<Class, Object> mClassCookies;
 
     private RuntimeException mStack;
+    private boolean mRecycled = false;
 
     /** @hide */
     @TestApi
@@ -528,6 +529,7 @@
         if (res == null) {
             res = new Parcel(0);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -556,7 +558,15 @@
      * the object after this call.
      */
     public final void recycle() {
-        if (DEBUG_RECYCLE) mStack = null;
+        if (mRecycled) {
+            Log.w(TAG, "Recycle called on unowned Parcel. (recycle twice?)", mStack);
+        }
+        mRecycled = true;
+
+        // We try to reset the entire object here, but in order to be
+        // able to print a stack when a Parcel is recycled twice, that
+        // is cleared in obtain instead.
+
         mClassCookies = null;
         freeBuffer();
 
@@ -5105,6 +5115,7 @@
         if (res == null) {
             res = new Parcel(obj);
         } else {
+            res.mRecycled = false;
             if (DEBUG_RECYCLE) {
                 res.mStack = new RuntimeException();
             }
@@ -5153,7 +5164,8 @@
     @Override
     protected void finalize() throws Throwable {
         if (DEBUG_RECYCLE) {
-            if (mStack != null) {
+            // we could always have this log on, but it's spammy
+            if (!mRecycled) {
                 Log.w(TAG, "Client did not call Parcel.recycle()", mStack);
             }
         }