CTS test for issue #32125907: Intent.replaceUnsafeExtras() corrupts original bundle

Check that we do the right stripping and don't corrupt the original
Bundle.

Change-Id: I155b3810e1e8aad3da601b656fdca74de2785ef0
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index 65da548..dbbbe15 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -38,6 +38,8 @@
 import android.util.AttributeSet;
 import android.util.Xml;
 
+import com.android.content.cts.DummyParcelable;
+
 import java.io.IOException;
 import java.io.Serializable;
 import java.net.URISyntaxException;
@@ -1750,6 +1752,49 @@
         assertEquals("foo/bar", Intent.normalizeMimeType("   foo/bar    "));
     }
 
+    public void testRemoveUnsafeExtras() {
+        final Intent intent = new Intent();
+        final DummyParcelable dummyParcelable = new DummyParcelable();
+        intent.removeUnsafeExtras();
+        assertNull(intent.getExtras());
+
+        // Check that removeUnsafeExtras keeps the same bundle if no changes are made.
+        Bundle origExtras = new Bundle();
+        origExtras.putString("foo", "bar");
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        Bundle newExtras = intent.getExtras();
+        assertEquals(1, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+
+        // Check that removeUnsafeExtras will strip non-framework parcelables without modifying
+        // the original extras bundle.
+        origExtras.putParcelable("baddy", dummyParcelable);
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        newExtras = intent.getExtras();
+        assertEquals(1, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+        assertEquals(2, origExtras.size());
+        assertEquals("bar", origExtras.get("foo"));
+        assertSame(dummyParcelable, origExtras.get("baddy"));
+
+        // Check that nested bad values will be stripped.
+        Bundle origSubExtras = new Bundle();
+        origSubExtras.putParcelable("baddy", dummyParcelable);
+        origExtras.putBundle("baddy", origSubExtras);
+        intent.replaceExtras(origExtras);
+        intent.removeUnsafeExtras();
+        newExtras = intent.getExtras();
+        assertEquals(2, newExtras.size());
+        assertEquals("bar", newExtras.get("foo"));
+        Bundle newSubExtras = newExtras.getBundle("baddy");
+        assertNotSame(origSubExtras, newSubExtras);
+        assertEquals(0, newSubExtras.size());
+        assertEquals(1, origSubExtras.size());
+        assertSame(dummyParcelable, origSubExtras.get("baddy"));
+    }
+
     private static class TestSerializable implements Serializable {
         static final long serialVersionUID = 1l;
         public String Name;
diff --git a/tests/tests/content/src/com/android/content/cts/DummyParcelable.java b/tests/tests/content/src/com/android/content/cts/DummyParcelable.java
new file mode 100644
index 0000000..5eb8418
--- /dev/null
+++ b/tests/tests/content/src/com/android/content/cts/DummyParcelable.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.content.cts;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class DummyParcelable implements Parcelable {
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+    }
+
+    public static final Parcelable.Creator<DummyParcelable> CREATOR
+            = new Parcelable.Creator<DummyParcelable>() {
+        public DummyParcelable createFromParcel(Parcel in) {
+            return new DummyParcelable();
+        }
+
+        public DummyParcelable[] newArray(int size) {
+            return new DummyParcelable[size];
+        }
+    };
+}