Switch Parcel to FastNative

Also fixes ParcelBenchmark to have bounded
memory usage to avoid OOM'ing during runs

Test: refactor, no behavior change

ParcelBenchmark results from bullhead
Before:
      timeReadByte 74.43ns
      timeReadInt 74.49ns
      timeReadLong 74.13ns
      timeWriteByte 81.81ns
      timeWriteInt 82.09ns
      timeWriteLong 81.84ns

After:
      timeReadByte 47.08ns
      timeReadInt 48.38ns
      timeReadLong 48.16ns
      timeWriteByte 55.90ns
      timeWriteInt 55.85ns
      timeWriteLong 56.58ns

Change-Id: I61b823d1d2beb86e00c196abd4dce65efa8fa7f0
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index f6e6ad6..85f999b 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -46,6 +46,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import dalvik.annotation.optimization.FastNative;
 import dalvik.system.VMRuntime;
 
 /**
@@ -254,22 +255,35 @@
     // see libbinder's binder/Status.h
     private static final int EX_TRANSACTION_FAILED = -129;
 
+    @FastNative
     private static native int nativeDataSize(long nativePtr);
+    @FastNative
     private static native int nativeDataAvail(long nativePtr);
+    @FastNative
     private static native int nativeDataPosition(long nativePtr);
+    @FastNative
     private static native int nativeDataCapacity(long nativePtr);
+    @FastNative
     private static native long nativeSetDataSize(long nativePtr, int size);
+    @FastNative
     private static native void nativeSetDataPosition(long nativePtr, int pos);
+    @FastNative
     private static native void nativeSetDataCapacity(long nativePtr, int size);
 
+    @FastNative
     private static native boolean nativePushAllowFds(long nativePtr, boolean allowFds);
+    @FastNative
     private static native void nativeRestoreAllowFds(long nativePtr, boolean lastValue);
 
     private static native void nativeWriteByteArray(long nativePtr, byte[] b, int offset, int len);
     private static native void nativeWriteBlob(long nativePtr, byte[] b, int offset, int len);
+    @FastNative
     private static native void nativeWriteInt(long nativePtr, int val);
+    @FastNative
     private static native void nativeWriteLong(long nativePtr, long val);
+    @FastNative
     private static native void nativeWriteFloat(long nativePtr, float val);
+    @FastNative
     private static native void nativeWriteDouble(long nativePtr, double val);
     private static native void nativeWriteString(long nativePtr, String val);
     private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);
@@ -277,9 +291,13 @@
 
     private static native byte[] nativeCreateByteArray(long nativePtr);
     private static native byte[] nativeReadBlob(long nativePtr);
+    @FastNative
     private static native int nativeReadInt(long nativePtr);
+    @FastNative
     private static native long nativeReadLong(long nativePtr);
+    @FastNative
     private static native float nativeReadFloat(long nativePtr);
+    @FastNative
     private static native double nativeReadDouble(long nativePtr);
     private static native String nativeReadString(long nativePtr);
     private static native IBinder nativeReadStrongBinder(long nativePtr);
@@ -294,6 +312,7 @@
             long nativePtr, byte[] data, int offset, int length);
     private static native long nativeAppendFrom(
             long thisNativePtr, long otherNativePtr, int offset, int length);
+    @FastNative
     private static native boolean nativeHasFileDescriptors(long nativePtr);
     private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
     private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
diff --git a/core/jni/android_os_Parcel.cpp b/core/jni/android_os_Parcel.cpp
index 0a8ae2b..8f7908a 100644
--- a/core/jni/android_os_Parcel.cpp
+++ b/core/jni/android_os_Parcel.cpp
@@ -722,33 +722,50 @@
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod gParcelMethods[] = {
-    {"nativeDataSize",            "!(J)I", (void*)android_os_Parcel_dataSize},
-    {"nativeDataAvail",           "!(J)I", (void*)android_os_Parcel_dataAvail},
-    {"nativeDataPosition",        "!(J)I", (void*)android_os_Parcel_dataPosition},
-    {"nativeDataCapacity",        "!(J)I", (void*)android_os_Parcel_dataCapacity},
-    {"nativeSetDataSize",         "!(JI)J", (void*)android_os_Parcel_setDataSize},
-    {"nativeSetDataPosition",     "!(JI)V", (void*)android_os_Parcel_setDataPosition},
-    {"nativeSetDataCapacity",     "!(JI)V", (void*)android_os_Parcel_setDataCapacity},
+    // @FastNative
+    {"nativeDataSize",            "(J)I", (void*)android_os_Parcel_dataSize},
+    // @FastNative
+    {"nativeDataAvail",           "(J)I", (void*)android_os_Parcel_dataAvail},
+    // @FastNative
+    {"nativeDataPosition",        "(J)I", (void*)android_os_Parcel_dataPosition},
+    // @FastNative
+    {"nativeDataCapacity",        "(J)I", (void*)android_os_Parcel_dataCapacity},
+    // @FastNative
+    {"nativeSetDataSize",         "(JI)J", (void*)android_os_Parcel_setDataSize},
+    // @FastNative
+    {"nativeSetDataPosition",     "(JI)V", (void*)android_os_Parcel_setDataPosition},
+    // @FastNative
+    {"nativeSetDataCapacity",     "(JI)V", (void*)android_os_Parcel_setDataCapacity},
 
-    {"nativePushAllowFds",        "!(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
-    {"nativeRestoreAllowFds",     "!(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
+    // @FastNative
+    {"nativePushAllowFds",        "(JZ)Z", (void*)android_os_Parcel_pushAllowFds},
+    // @FastNative
+    {"nativeRestoreAllowFds",     "(JZ)V", (void*)android_os_Parcel_restoreAllowFds},
 
     {"nativeWriteByteArray",      "(J[BII)V", (void*)android_os_Parcel_writeNative},
     {"nativeWriteBlob",           "(J[BII)V", (void*)android_os_Parcel_writeBlob},
-    {"nativeWriteInt",            "!(JI)V", (void*)android_os_Parcel_writeInt},
-    {"nativeWriteLong",           "!(JJ)V", (void*)android_os_Parcel_writeLong},
-    {"nativeWriteFloat",          "!(JF)V", (void*)android_os_Parcel_writeFloat},
-    {"nativeWriteDouble",         "!(JD)V", (void*)android_os_Parcel_writeDouble},
+    // @FastNative
+    {"nativeWriteInt",            "(JI)V", (void*)android_os_Parcel_writeInt},
+    // @FastNative
+    {"nativeWriteLong",           "(JJ)V", (void*)android_os_Parcel_writeLong},
+    // @FastNative
+    {"nativeWriteFloat",          "(JF)V", (void*)android_os_Parcel_writeFloat},
+    // @FastNative
+    {"nativeWriteDouble",         "(JD)V", (void*)android_os_Parcel_writeDouble},
     {"nativeWriteString",         "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeString},
     {"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
     {"nativeWriteFileDescriptor", "(JLjava/io/FileDescriptor;)J", (void*)android_os_Parcel_writeFileDescriptor},
 
     {"nativeCreateByteArray",     "(J)[B", (void*)android_os_Parcel_createByteArray},
     {"nativeReadBlob",            "(J)[B", (void*)android_os_Parcel_readBlob},
-    {"nativeReadInt",             "!(J)I", (void*)android_os_Parcel_readInt},
-    {"nativeReadLong",            "!(J)J", (void*)android_os_Parcel_readLong},
-    {"nativeReadFloat",           "!(J)F", (void*)android_os_Parcel_readFloat},
-    {"nativeReadDouble",          "!(J)D", (void*)android_os_Parcel_readDouble},
+    // @FastNative
+    {"nativeReadInt",             "(J)I", (void*)android_os_Parcel_readInt},
+    // @FastNative
+    {"nativeReadLong",            "(J)J", (void*)android_os_Parcel_readLong},
+    // @FastNative
+    {"nativeReadFloat",           "(J)F", (void*)android_os_Parcel_readFloat},
+    // @FastNative
+    {"nativeReadDouble",          "(J)D", (void*)android_os_Parcel_readDouble},
     {"nativeReadString",          "(J)Ljava/lang/String;", (void*)android_os_Parcel_readString},
     {"nativeReadStrongBinder",    "(J)Landroid/os/IBinder;", (void*)android_os_Parcel_readStrongBinder},
     {"nativeReadFileDescriptor",  "(J)Ljava/io/FileDescriptor;", (void*)android_os_Parcel_readFileDescriptor},
@@ -765,7 +782,8 @@
     {"nativeMarshall",            "(J)[B", (void*)android_os_Parcel_marshall},
     {"nativeUnmarshall",          "(J[BII)J", (void*)android_os_Parcel_unmarshall},
     {"nativeAppendFrom",          "(JJII)J", (void*)android_os_Parcel_appendFrom},
-    {"nativeHasFileDescriptors",  "!(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
+    // @FastNative
+    {"nativeHasFileDescriptors",  "(J)Z", (void*)android_os_Parcel_hasFileDescriptors},
     {"nativeWriteInterfaceToken", "(JLjava/lang/String;)V", (void*)android_os_Parcel_writeInterfaceToken},
     {"nativeEnforceInterface",    "(JLjava/lang/String;)V", (void*)android_os_Parcel_enforceInterface},
 
diff --git a/core/tests/benchmarks/src/android/os/ParcelBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
index 4bd2d00..6c45ae8 100644
--- a/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
+++ b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
@@ -20,12 +20,15 @@
 import com.google.caliper.BeforeExperiment;
 
 public class ParcelBenchmark {
+    private static final int INNER_REPS = 1000;
 
     private Parcel mParcel;
 
     @BeforeExperiment
     protected void setUp() {
         mParcel = Parcel.obtain();
+        mParcel.setDataPosition(0);
+        mParcel.setDataCapacity(INNER_REPS * 8);
     }
 
     @AfterExperiment
@@ -36,43 +39,58 @@
 
     public void timeWriteByte(int reps) {
         final byte val = 0xF;
-        for (int i = 0; i < reps; i++) {
-            mParcel.writeByte(val);
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.writeByte(val);
+            }
         }
     }
 
     public void timeReadByte(int reps) {
-        mParcel.setDataCapacity(reps);
-        for (int i = 0; i < reps; i++) {
-            mParcel.readByte();
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.readByte();
+            }
         }
     }
 
     public void timeWriteInt(int reps) {
         final int val = 0xF;
-        for (int i = 0; i < reps; i++) {
-            mParcel.writeInt(val);
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.writeInt(val);
+            }
         }
     }
 
     public void timeReadInt(int reps) {
-        mParcel.setDataCapacity(reps << 2);
-        for (int i = 0; i < reps; i++) {
-            mParcel.readInt();
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.readInt();
+            }
         }
     }
 
     public void timeWriteLong(int reps) {
         final long val = 0xF;
-        for (int i = 0; i < reps; i++) {
-            mParcel.writeLong(val);
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.writeLong(val);
+            }
         }
     }
 
     public void timeReadLong(int reps) {
-        mParcel.setDataCapacity(reps << 3);
-        for (int i = 0; i < reps; i++) {
-            mParcel.readLong();
+        for (int i = 0; i < (reps / INNER_REPS); i++) {
+            mParcel.setDataPosition(0);
+            for (int j = 0; j < INNER_REPS; j++) {
+                mParcel.readLong();
+            }
         }
     }
 }