summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brad Fitzpatrick <bradfitz@android.com> 2010-07-13 15:33:35 -0700
committer Brad Fitzpatrick <bradfitz@android.com> 2010-07-13 15:45:18 -0700
commit837a0d0fb2c3fba8082d47d04cb6120af1eb9a54 (patch)
tree91aa19308f64695c7b03b06c5f7268a7a5997cfd
parenta65139634e2203230a76b8f510fe3cb21d1b3843 (diff)
Add Parcel::readExceptionCode() and Parcel::writeNoException()
Add native Parcel methods analogous to the Java versions. Currently, these don't do much, but upcoming StrictMode work changes the RPC calling conventions in some cases, so it's important that everybody uses these consistently, rather than having a lot of code trying to parse RPC responses out of Parcels themselves. As a summary, the current convention that Java Binder services use is to prepend the reply Parcel with an int32 signaling the exception status: 0: no exception -1: Security exception -2: Bad Parcelable -3: ... -4: ... -5: ... ... followed by Parceled String if the exception code is non-zero. With an upcoming change, it'll be the case that a response Parcel can, non-exceptionally return rich data in the header, and also return data to the caller. The important thing to note in this new case is that the first int32 in the reply parcel *will not be zero*, so anybody manually checking for it with reply.readInt32() will get false negative failures. Short summary: If you're calling into a Java service and manually checking the exception status with reply.readInt32(), change it to reply.readExceptionCode(). Change-Id: I23f9a0e53a8cfbbd9759242cfde16723641afe04
-rw-r--r--include/binder/Parcel.h14
-rw-r--r--libs/binder/IPermissionController.cpp8
-rw-r--r--libs/binder/IServiceManager.cpp2
-rw-r--r--libs/binder/Parcel.cpp11
4 files changed, 28 insertions, 7 deletions
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 2cc4db9391..3aba5f6bfb 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -103,6 +103,11 @@ public:
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
+ // Like Parcel.java's writeNoException(). Just writes a zero int32.
+ // Currently the native implementation doesn't do any of the StrictMode
+ // stack gathering and serialization that the Java implementation does.
+ status_t writeNoException();
+
void remove(size_t start, size_t amt);
status_t read(void* outData, size_t len) const;
@@ -125,7 +130,14 @@ public:
sp<IBinder> readStrongBinder() const;
wp<IBinder> readWeakBinder() const;
status_t read(Flattenable& val) const;
-
+
+ // Like Parcel.java's readExceptionCode(). Reads the first int32
+ // off of a Parcel's header, returning 0 or the negative error
+ // code on exceptions, but also deals with skipping over rich
+ // response headers. Callers should use this to read & parse the
+ // response headers rather than doing it by hand.
+ int32_t readExceptionCode() const;
+
// Retrieve native_handle from the parcel. This returns a copy of the
// parcel's native_handle (the caller takes ownership). The caller
// must free the native_handle with native_handle_close() and
diff --git a/libs/binder/IPermissionController.cpp b/libs/binder/IPermissionController.cpp
index bff4c9bd7d..e13036ff42 100644
--- a/libs/binder/IPermissionController.cpp
+++ b/libs/binder/IPermissionController.cpp
@@ -36,7 +36,7 @@ public:
: BpInterface<IPermissionController>(impl)
{
}
-
+
virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid)
{
Parcel data, reply;
@@ -46,7 +46,7 @@ public:
data.writeInt32(uid);
remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply);
// fail on exception
- if (reply.readInt32() != 0) return 0;
+ if (reply.readExceptionCode() != 0) return 0;
return reply.readInt32() != 0;
}
};
@@ -66,8 +66,7 @@ status_t BnPermissionController::onTransact(
int32_t pid = data.readInt32();
int32_t uid = data.readInt32();
bool res = checkPermission(permission, pid, uid);
- // write exception
- reply->writeInt32(0);
+ reply->writeNoException();
reply->writeInt32(res ? 1 : 0);
return NO_ERROR;
} break;
@@ -77,4 +76,3 @@ status_t BnPermissionController::onTransact(
}
}; // namespace android
-
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index a3a3f0ee00..1fa4c3579c 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -158,7 +158,7 @@ public:
data.writeString16(name);
data.writeStrongBinder(service);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
- return err == NO_ERROR ? reply.readInt32() : err;
+ return err == NO_ERROR ? reply.readExceptionCode() : err;
}
virtual Vector<String16> listServices()
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index c2574bd0ba..47be1bf69c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -754,6 +754,11 @@ restart_write:
goto restart_write;
}
+status_t Parcel::writeNoException()
+{
+ return writeInt32(0);
+}
+
void Parcel::remove(size_t start, size_t amt)
{
LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
@@ -942,6 +947,12 @@ wp<IBinder> Parcel::readWeakBinder() const
return val;
}
+int32_t Parcel::readExceptionCode() const
+{
+ int32_t exception_code = readAligned<int32_t>();
+ // TODO: skip over the response header here, once that's in.
+ return exception_code;
+}
native_handle* Parcel::readNativeHandle() const
{