camera: Make some binder interfaces compatible with AIDL

Done:
* ICameraService
* ICameraServiceListener

Partial:
* ICamera (disconnect only)
* IProCameraUser (disconnect only)

Bug: 9213377
Change-Id: I8e2e6e05cfd02ec36be1d5b2c551f10ffb43b5b4
diff --git a/camera/ICamera.cpp b/camera/ICamera.cpp
index 732c204..12356f0 100644
--- a/camera/ICamera.cpp
+++ b/camera/ICamera.cpp
@@ -66,6 +66,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
         remote()->transact(DISCONNECT, data, &reply);
+        reply.readExceptionCode();
     }
 
     // pass the buffered IGraphicBufferProducer to the camera service
@@ -281,6 +282,7 @@
             ALOGV("DISCONNECT");
             CHECK_INTERFACE(ICamera, data, reply);
             disconnect();
+            reply->writeNoException();
             return NO_ERROR;
         } break;
         case SET_PREVIEW_TEXTURE: {
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 134f7f0..819e410 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -15,6 +15,9 @@
 ** limitations under the License.
 */
 
+#define LOG_TAG "BpCameraService"
+#include <utils/Log.h>
+
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -31,6 +34,53 @@
 
 namespace android {
 
+namespace {
+
+enum {
+    EX_SECURITY = -1,
+    EX_BAD_PARCELABLE = -2,
+    EX_ILLEGAL_ARGUMENT = -3,
+    EX_NULL_POINTER = -4,
+    EX_ILLEGAL_STATE = -5,
+    EX_HAS_REPLY_HEADER = -128,  // special; see below
+};
+
+static bool readExceptionCode(Parcel& reply) {
+    int32_t exceptionCode = reply.readExceptionCode();
+
+    if (exceptionCode != 0) {
+        const char* errorMsg;
+        switch(exceptionCode) {
+            case EX_SECURITY:
+                errorMsg = "Security";
+                break;
+            case EX_BAD_PARCELABLE:
+                errorMsg = "BadParcelable";
+                break;
+            case EX_NULL_POINTER:
+                errorMsg = "NullPointer";
+                break;
+            case EX_ILLEGAL_STATE:
+                errorMsg = "IllegalState";
+                break;
+            // Binder should be handling this code inside Parcel::readException
+            // but lets have a to-string here anyway just in case.
+            case EX_HAS_REPLY_HEADER:
+                errorMsg = "HasReplyHeader";
+                break;
+            default:
+                errorMsg = "Unknown";
+        }
+
+        ALOGE("Binder transmission error %s (%d)", errorMsg, exceptionCode);
+        return true;
+    }
+
+    return false;
+}
+
+};
+
 class BpCameraService: public BpInterface<ICameraService>
 {
 public:
@@ -45,6 +95,8 @@
         Parcel data, reply;
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         remote()->transact(BnCameraService::GET_NUMBER_OF_CAMERAS, data, &reply);
+
+        if (readExceptionCode(reply)) return 0;
         return reply.readInt32();
     }
 
@@ -55,9 +107,14 @@
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeInt32(cameraId);
         remote()->transact(BnCameraService::GET_CAMERA_INFO, data, &reply);
-        cameraInfo->facing = reply.readInt32();
-        cameraInfo->orientation = reply.readInt32();
-        return reply.readInt32();
+
+        if (readExceptionCode(reply)) return -EPROTO;
+        status_t result = reply.readInt32();
+        if (reply.readInt32() != 0) {
+            cameraInfo->facing = reply.readInt32();
+            cameraInfo->orientation = reply.readInt32();
+        }
+        return result;
     }
 
     // connect to camera service
@@ -71,6 +128,8 @@
         data.writeString16(clientPackageName);
         data.writeInt32(clientUid);
         remote()->transact(BnCameraService::CONNECT, data, &reply);
+
+        if (readExceptionCode(reply)) return NULL;
         return interface_cast<ICamera>(reply.readStrongBinder());
     }
 
@@ -85,6 +144,8 @@
         data.writeString16(clientPackageName);
         data.writeInt32(clientUid);
         remote()->transact(BnCameraService::CONNECT_PRO, data, &reply);
+
+        if (readExceptionCode(reply)) return NULL;
         return interface_cast<IProCameraUser>(reply.readStrongBinder());
     }
 
@@ -94,6 +155,8 @@
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeStrongBinder(listener->asBinder());
         remote()->transact(BnCameraService::ADD_LISTENER, data, &reply);
+
+        if (readExceptionCode(reply)) return -EPROTO;
         return reply.readInt32();
     }
 
@@ -103,6 +166,8 @@
         data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
         data.writeStrongBinder(listener->asBinder());
         remote()->transact(BnCameraService::REMOVE_LISTENER, data, &reply);
+
+        if (readExceptionCode(reply)) return -EPROTO;
         return reply.readInt32();
     }
 };
@@ -117,17 +182,22 @@
     switch(code) {
         case GET_NUMBER_OF_CAMERAS: {
             CHECK_INTERFACE(ICameraService, data, reply);
+            reply->writeNoException();
             reply->writeInt32(getNumberOfCameras());
             return NO_ERROR;
         } break;
         case GET_CAMERA_INFO: {
             CHECK_INTERFACE(ICameraService, data, reply);
-            CameraInfo cameraInfo;
+            CameraInfo cameraInfo = CameraInfo();
             memset(&cameraInfo, 0, sizeof(cameraInfo));
             status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
+            reply->writeNoException();
+            reply->writeInt32(result);
+
+            // Fake a parcelable object here
+            reply->writeInt32(1); // means the parcelable is included
             reply->writeInt32(cameraInfo.facing);
             reply->writeInt32(cameraInfo.orientation);
-            reply->writeInt32(result);
             return NO_ERROR;
         } break;
         case CONNECT: {
@@ -139,17 +209,20 @@
             int32_t clientUid = data.readInt32();
             sp<ICamera> camera = connect(cameraClient, cameraId,
                     clientName, clientUid);
+            reply->writeNoException();
             reply->writeStrongBinder(camera->asBinder());
             return NO_ERROR;
         } break;
         case CONNECT_PRO: {
             CHECK_INTERFACE(ICameraService, data, reply);
-            sp<IProCameraCallbacks> cameraClient = interface_cast<IProCameraCallbacks>(data.readStrongBinder());
+            sp<IProCameraCallbacks> cameraClient =
+                interface_cast<IProCameraCallbacks>(data.readStrongBinder());
             int32_t cameraId = data.readInt32();
             const String16 clientName = data.readString16();
             int32_t clientUid = data.readInt32();
             sp<IProCameraUser> camera = connect(cameraClient, cameraId,
                                                 clientName, clientUid);
+            reply->writeNoException();
             reply->writeStrongBinder(camera->asBinder());
             return NO_ERROR;
         } break;
@@ -157,6 +230,7 @@
             CHECK_INTERFACE(ICameraService, data, reply);
             sp<ICameraServiceListener> listener =
                 interface_cast<ICameraServiceListener>(data.readStrongBinder());
+            reply->writeNoException();
             reply->writeInt32(addListener(listener));
             return NO_ERROR;
         } break;
@@ -164,6 +238,7 @@
             CHECK_INTERFACE(ICameraService, data, reply);
             sp<ICameraServiceListener> listener =
                 interface_cast<ICameraServiceListener>(data.readStrongBinder());
+            reply->writeNoException();
             reply->writeInt32(removeListener(listener));
             return NO_ERROR;
         } break;
diff --git a/camera/ICameraServiceListener.cpp b/camera/ICameraServiceListener.cpp
index 640ee35..b2f1729 100644
--- a/camera/ICameraServiceListener.cpp
+++ b/camera/ICameraServiceListener.cpp
@@ -54,6 +54,8 @@
                            data,
                            &reply,
                            IBinder::FLAG_ONEWAY);
+
+        reply.readExceptionCode();
     }
 };
 
@@ -73,6 +75,7 @@
             int32_t cameraId = data.readInt32();
 
             onStatusChanged(status, cameraId);
+            reply->writeNoException();
 
             return NO_ERROR;
         } break;
diff --git a/camera/IProCameraUser.cpp b/camera/IProCameraUser.cpp
index 4c4dec3..015cb5c 100644
--- a/camera/IProCameraUser.cpp
+++ b/camera/IProCameraUser.cpp
@@ -162,6 +162,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IProCameraUser::getInterfaceDescriptor());
         remote()->transact(DISCONNECT, data, &reply);
+        reply.readExceptionCode();
     }
 
     virtual status_t connect(const sp<IProCameraCallbacks>& cameraClient)
@@ -307,6 +308,7 @@
             ALOGV("DISCONNECT");
             CHECK_INTERFACE(IProCameraUser, data, reply);
             disconnect();
+            reply->writeNoException();
             return NO_ERROR;
         } break;
         case CONNECT: {
diff --git a/include/camera/ICamera.h b/include/camera/ICamera.h
index b2125bd..f3a186e 100644
--- a/include/camera/ICamera.h
+++ b/include/camera/ICamera.h
@@ -32,6 +32,9 @@
 
 class ICamera: public IInterface
 {
+    /**
+     * Keep up-to-date with ICamera.aidl in frameworks/base
+     */
 public:
     DECLARE_META_INTERFACE(Camera);
 
diff --git a/include/camera/ICameraClient.h b/include/camera/ICameraClient.h
index b30aa7a..1584dba 100644
--- a/include/camera/ICameraClient.h
+++ b/include/camera/ICameraClient.h
@@ -28,6 +28,9 @@
 
 class ICameraClient: public IInterface
 {
+    /**
+     * Keep up-to-date with ICameraClient.aidl in frameworks/base
+     */
 public:
     DECLARE_META_INTERFACE(CameraClient);
 
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index aaf6eb3..3c2e60a 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -32,6 +32,9 @@
 class ICameraService : public IInterface
 {
 public:
+    /**
+     * Keep up-to-date with ICameraService.aidl in frameworks/base
+     */
     enum {
         GET_NUMBER_OF_CAMERAS = IBinder::FIRST_CALL_TRANSACTION,
         GET_CAMERA_INFO,
diff --git a/include/camera/ICameraServiceListener.h b/include/camera/ICameraServiceListener.h
index f2a11c2..0a0e43a 100644
--- a/include/camera/ICameraServiceListener.h
+++ b/include/camera/ICameraServiceListener.h
@@ -26,6 +26,9 @@
 
 class ICameraServiceListener : public IInterface
 {
+    /**
+     * Keep up-to-date with ICameraServiceListener.aidl in frameworks/base
+     */
 public:
 
     /**
diff --git a/include/camera/IProCameraCallbacks.h b/include/camera/IProCameraCallbacks.h
index 563ec17..c774698 100644
--- a/include/camera/IProCameraCallbacks.h
+++ b/include/camera/IProCameraCallbacks.h
@@ -30,6 +30,9 @@
 
 class IProCameraCallbacks : public IInterface
 {
+    /**
+     * Keep up-to-date with IProCameraCallbacks.aidl in frameworks/base
+     */
 public:
     DECLARE_META_INTERFACE(ProCameraCallbacks);
 
diff --git a/include/camera/IProCameraUser.h b/include/camera/IProCameraUser.h
index 45b818c..2ccc4d2 100644
--- a/include/camera/IProCameraUser.h
+++ b/include/camera/IProCameraUser.h
@@ -34,6 +34,9 @@
 
 class IProCameraUser: public IInterface
 {
+    /**
+     * Keep up-to-date with IProCameraUser.aidl in frameworks/base
+     */
 public:
     DECLARE_META_INTERFACE(ProCameraUser);