Rethrow remote's ServiceSpecificException

Certain system services would like to throw exceptions
with specific error codes, so that the framework can catch
these specific conditions and express them appropriately.

Bug: 25800533
Change-Id: I94b3d30fa131f5e14bba893c971615840085459f
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 1e879f2..5d6b8aa 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -231,6 +231,7 @@
     private static final int VAL_SIZEF = 27;
 
     // The initial int32 in a Binder call's reply Parcel header:
+    // Keep these in sync with libbinder's binder/Status.h.
     private static final int EX_SECURITY = -1;
     private static final int EX_BAD_PARCELABLE = -2;
     private static final int EX_ILLEGAL_ARGUMENT = -3;
@@ -238,7 +239,11 @@
     private static final int EX_ILLEGAL_STATE = -5;
     private static final int EX_NETWORK_MAIN_THREAD = -6;
     private static final int EX_UNSUPPORTED_OPERATION = -7;
+    private static final int EX_SERVICE_SPECIFIC = -8;
     private static final int EX_HAS_REPLY_HEADER = -128;  // special; see below
+    // EX_TRANSACTION_FAILED is used exclusively in native code.
+    // see libbinder's binder/Status.h
+    private static final int EX_TRANSACTION_FAILED = -129;
 
     private static native int nativeDataSize(long nativePtr);
     private static native int nativeDataAvail(long nativePtr);
@@ -1515,6 +1520,8 @@
             code = EX_NETWORK_MAIN_THREAD;
         } else if (e instanceof UnsupportedOperationException) {
             code = EX_UNSUPPORTED_OPERATION;
+        } else if (e instanceof ServiceSpecificException) {
+            code = EX_SERVICE_SPECIFIC;
         }
         writeInt(code);
         StrictMode.clearGatheredViolations();
@@ -1525,6 +1532,9 @@
             throw new RuntimeException(e);
         }
         writeString(e.getMessage());
+        if (e instanceof ServiceSpecificException) {
+            writeInt(((ServiceSpecificException)e).errorCode);
+        }
     }
 
     /**
@@ -1635,6 +1645,8 @@
                 throw new NetworkOnMainThreadException();
             case EX_UNSUPPORTED_OPERATION:
                 throw new UnsupportedOperationException(msg);
+            case EX_SERVICE_SPECIFIC:
+                throw new ServiceSpecificException(readInt(), msg);
         }
         throw new RuntimeException("Unknown exception code: " + code
                 + " msg " + msg);