Implement error handling for C++ services

Bug: 25615695
Test: unit tests continue to pass.

Change-Id: I24f4f3a5a7b95438ab7daa707d2b4598b33b8302
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index b17587e..ee7ec1a 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -43,12 +43,15 @@
 namespace internals {
 namespace {
 
+const char kStatusVarName[] = "_aidl_status";
 const char kReturnVarName[] = "_aidl_return";
 const char kAndroidStatusLiteral[] = "android::status_t";
 const char kAndroidParcelLiteral[] = "android::Parcel";
+const char kBinderStatusLiteral[] = "android::binder::Status";
 const char kIBinderHeader[] = "binder/IBinder.h";
 const char kIInterfaceHeader[] = "binder/IInterface.h";
 const char kParcelHeader[] = "binder/Parcel.h";
+const char kStatusHeader[] = "binder/Status.h";
 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
 
 unique_ptr<AstNode> BreakOnStatusNotOk() {
@@ -59,6 +62,15 @@
   return unique_ptr<AstNode>(ret);
 }
 
+unique_ptr<AstNode> GotoErrorOnBadStatus() {
+  IfStatement* ret = new IfStatement(new Comparison(
+      new LiteralExpression("status"), "!=",
+      new LiteralExpression("android::OK")));
+  ret->OnTrue()->AddLiteral("goto error");
+  return unique_ptr<AstNode>(ret);
+}
+
+
 unique_ptr<AstNode> ReturnOnStatusNotOk() {
   IfStatement* ret = new IfStatement(new Comparison(
       new LiteralExpression("status"), "!=",
@@ -143,7 +155,7 @@
   }
 
   return unique_ptr<Declaration>{
-      new MethodDecl{kAndroidStatusLiteral,
+      new MethodDecl{kBinderStatusLiteral,
                      method.GetName(),
                      BuildArgList(types, method, true /* for method decl */),
                      modifiers}};
@@ -254,7 +266,7 @@
   const string i_name = ClassName(interface, ClassNames::INTERFACE);
   const string bp_name = ClassName(interface, ClassNames::CLIENT);
   unique_ptr<MethodImpl> ret{new MethodImpl{
-      kAndroidStatusLiteral, bp_name, method.GetName(),
+      kBinderStatusLiteral, bp_name, method.GetName(),
       ArgList{BuildArgList(types, method, true /* for method decl */)}}};
   StatementBlock* b = ret->GetStatementBlock();
 
@@ -263,18 +275,20 @@
   // Even if we're oneway, the transact method still takes a parcel.
   b->AddLiteral(StringPrintf("%s reply", kAndroidParcelLiteral));
 
-  // And declare the status variable we need for error handling.
+  // Declare the status_t variable we need for error handling.
   b->AddLiteral(StringPrintf("%s status", kAndroidStatusLiteral));
+  // We unconditionally return a Status object.
+  b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
 
   // Add the name of the interface we're hoping to call.
   b->AddStatement(new Assignment(
       "status",
       new MethodCall("data.writeInterfaceToken", "getInterfaceDescriptor()")));
-  b->AddStatement(ReturnOnStatusNotOk());
+  b->AddStatement(GotoErrorOnBadStatus());
 
   // Serialization looks roughly like:
   //     status = data.WriteInt32(in_param_name);
-  //     if (status != android::OK) { return status; }
+  //     if (status != android::OK) { goto error; }
   for (const AidlArgument* a : method.GetInArguments()) {
     const Type* type = types.Find(a->GetType().GetName());
     string method =
@@ -285,7 +299,7 @@
     b->AddStatement(new Assignment(
         "status",
         new MethodCall("data." + method, ArgList(var_name))));
-    b->AddStatement(ReturnOnStatusNotOk());
+    b->AddStatement(GotoErrorOnBadStatus());
   }
 
   // Invoke the transaction on the remote binder and confirm status.
@@ -302,20 +316,21 @@
       "status",
       new MethodCall("remote()->transact",
                      ArgList(args))));
-  b->AddStatement(ReturnOnStatusNotOk());
+  b->AddStatement(GotoErrorOnBadStatus());
 
   if (!interface.IsOneway() && !method.IsOneway()) {
     // Strip off the exception header and fail if we see a remote exception.
-    // if (reply.readExceptionCode()) {
-    //   status = android::FAILED_TRANSACTION;
-    //   return status;
-    // }
+    // status = _aidl_status.readFromParcel(reply);
+    // if (status != android::OK) { goto error; }
+    // if (!_aidl_status.isOk()) { return _aidl_status; }
+    b->AddStatement(new Assignment(
+        "status", StringPrintf("%s.readFromParcel(reply)", kStatusVarName)));
+    b->AddStatement(GotoErrorOnBadStatus());
     IfStatement* exception_check = new IfStatement(
-        new LiteralExpression("reply.readExceptionCode()"));
+        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
     b->AddStatement(exception_check);
-    exception_check->OnTrue()->AddStatement(
-        new Assignment("status", "android::FAILED_TRANSACTION"));
-    exception_check->OnTrue()->AddLiteral("return status");
+    exception_check->OnTrue()->AddLiteral(
+        StringPrintf("return %s", kStatusVarName));
   }
 
   // Type checking should guarantee that nothing below emits code until "return
@@ -329,13 +344,13 @@
     b->AddStatement(new Assignment(
         "status",
         new MethodCall("reply." + method_call, ArgList(kReturnVarName))));
-    b->AddStatement(ReturnOnStatusNotOk());
+    b->AddStatement(GotoErrorOnBadStatus());
   }
 
   for (const AidlArgument* a : method.GetOutArguments()) {
     // Deserialization looks roughly like:
     //     status = reply.ReadInt32(out_param_name);
-    //     if (status != android::OK) { return status; }
+    //     if (status != android::OK) { goto error; }
     string method =
       types.Find(a->GetType().GetName())
         ->ReadFromParcelMethod(a->GetType().IsArray());
@@ -343,10 +358,18 @@
     b->AddStatement(new Assignment(
         "status",
         new MethodCall("reply." + method, ArgList(a->GetName()))));
-    b->AddStatement(ReturnOnStatusNotOk());
+    b->AddStatement(GotoErrorOnBadStatus());
   }
 
-  b->AddLiteral("return status");
+  // If we've gotten to here, one of two things is true:
+  //   1) We've read some bad status_t
+  //   2) We've only read status_t == OK and there was no exception in the
+  //      response.
+  // In both cases, we're free to set Status from the status_t and return.
+  b->AddLiteral("error:\n", false /* no semicolon */);
+  b->AddLiteral(
+      StringPrintf("%s.setFromStatusT(status)", kStatusVarName));
+  b->AddLiteral(StringPrintf("return %s", kStatusVarName));
 
   return unique_ptr<Declaration>(ret.release());
 }
@@ -425,15 +448,24 @@
   }
 
   // Call the actual method.  This is implemented by the subclass.
-  b->AddStatement(new Assignment{
-      "status", new MethodCall{
+  vector<unique_ptr<AstNode>> status_args;
+  status_args.emplace_back(new MethodCall(
           method.GetName(),
-          BuildArgList(types, method, false /* not for method decl */)}});
-  b->AddStatement(BreakOnStatusNotOk());
+          BuildArgList(types, method, false /* not for method decl */)));
+  b->AddStatement(new Statement(new MethodCall(
+      StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
+      ArgList(std::move(status_args)))));
 
-  // Write that we encountered no exceptions during transaction handling.
-  b->AddStatement(new Assignment("status", "reply->writeNoException()"));
-  b->AddStatement(BreakOnStatusNotOk());
+  // Write exceptions during transaction handling to parcel.
+  if (!method.IsOneway()) {
+    b->AddStatement(new Assignment(
+        "status", StringPrintf("%s.writeToParcel(reply)", kStatusVarName)));
+    b->AddStatement(BreakOnStatusNotOk());
+    IfStatement* exception_check = new IfStatement(
+        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
+    b->AddStatement(exception_check);
+    exception_check->OnTrue()->AddLiteral("break");
+  }
 
   // If we have a return value, write it first.
   if (return_type != types.VoidType()) {
@@ -481,7 +513,7 @@
                "uint32_t flags"}}
       }};
 
-  // Declare the status variable
+  // Declare the status_t variable
   on_transact->GetStatementBlock()->AddLiteral(
       StringPrintf("%s status", kAndroidStatusLiteral));
 
@@ -503,6 +535,16 @@
   b->AddLiteral(
       "status = android::BBinder::onTransact(code, data, reply, flags)");
 
+  // If we saw a null reference, we can map that to an appropriate exception.
+  IfStatement* null_check = new IfStatement(
+      new LiteralExpression("status == android::UNEXPECTED_NULL"));
+  on_transact->GetStatementBlock()->AddStatement(null_check);
+  null_check->OnTrue()->AddStatement(new Assignment(
+      "status",
+      StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
+                   ".writeToParcel(reply)",
+                   kBinderStatusLiteral, kBinderStatusLiteral)));
+
   // Finally, the server's onTransact method just returns a status code.
   on_transact->GetStatementBlock()->AddLiteral("return status");
 
@@ -606,7 +648,7 @@
 unique_ptr<Document> BuildInterfaceHeader(const TypeNamespace& types,
                                           const AidlInterface& interface) {
   set<string> includes = { kIBinderHeader, kIInterfaceHeader,
-                           kStrongPointerHeader };
+                           kStatusHeader, kStrongPointerHeader };
 
   for (const auto& method : interface.GetMethods()) {
     for (const auto& argument : method->GetArguments()) {
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index bb1f490..c2683e3 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -67,11 +67,11 @@
 public:
 explicit BpComplexTypeInterface(const android::sp<android::IBinder>& impl);
 virtual ~BpComplexTypeInterface() = default;
-android::status_t Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) override;
-android::status_t Piff(int32_t times) override;
-android::status_t TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) override;
-android::status_t StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) override;
-android::status_t BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) override;
+android::binder::Status Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) override;
+android::binder::Status Piff(int32_t times) override;
+android::binder::Status TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) override;
+android::binder::Status StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) override;
+android::binder::Status BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) override;
 };  // class BpComplexTypeInterface
 
 }  // namespace os
@@ -92,151 +92,178 @@
     : BpInterface<IComplexTypeInterface>(impl){
 }
 
-android::status_t BpComplexTypeInterface::Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) {
+android::binder::Status BpComplexTypeInterface::Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeInt32Vector(goes_in);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeDoubleVector(*goes_in_and_out);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IComplexTypeInterface::SEND, data, &reply);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-if (reply.readExceptionCode()) {
-status = android::FAILED_TRANSACTION;
-return status;
+status = _aidl_status.readFromParcel(reply);
+if (((status) != (android::OK))) {
+goto error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
 }
 status = reply.readInt32Vector(_aidl_return);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = reply.readDoubleVector(goes_in_and_out);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = reply.readBoolVector(goes_out);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
-android::status_t BpComplexTypeInterface::Piff(int32_t times) {
+android::binder::Status BpComplexTypeInterface::Piff(int32_t times) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeInt32(times);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IComplexTypeInterface::PIFF, data, &reply, android::IBinder::FLAG_ONEWAY);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
-android::status_t BpComplexTypeInterface::TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) {
+android::binder::Status BpComplexTypeInterface::TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeStrongBinder(IFooType::asBinder(f));
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IComplexTypeInterface::TAKESABINDER, data, &reply);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-if (reply.readExceptionCode()) {
-status = android::FAILED_TRANSACTION;
-return status;
+status = _aidl_status.readFromParcel(reply);
+if (((status) != (android::OK))) {
+goto error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
 }
 status = reply.readStrongBinder(_aidl_return);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
-android::status_t BpComplexTypeInterface::StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) {
+android::binder::Status BpComplexTypeInterface::StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeString16Vector(input);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IComplexTypeInterface::STRINGLISTMETHOD, data, &reply);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-if (reply.readExceptionCode()) {
-status = android::FAILED_TRANSACTION;
-return status;
+status = _aidl_status.readFromParcel(reply);
+if (((status) != (android::OK))) {
+goto error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
 }
 status = reply.readString16Vector(_aidl_return);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = reply.readString16Vector(output);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
-android::status_t BpComplexTypeInterface::BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) {
+android::binder::Status BpComplexTypeInterface::BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeStrongBinderVector(input);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IComplexTypeInterface::BINDERLISTMETHOD, data, &reply);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-if (reply.readExceptionCode()) {
-status = android::FAILED_TRANSACTION;
-return status;
+status = _aidl_status.readFromParcel(reply);
+if (((status) != (android::OK))) {
+goto error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
 }
 status = reply.readStrongBinderVector(_aidl_return);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = reply.readStrongBinderVector(output);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
 }  // namespace os
@@ -295,12 +322,12 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return);
+android::binder::Status _aidl_status(Send(in_goes_in, &in_goes_in_and_out, &out_goes_out, &_aidl_return));
+status = _aidl_status.writeToParcel(reply);
 if (((status) != (android::OK))) {
 break;
 }
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
+if (!_aidl_status.isOk()) {
 break;
 }
 status = reply->writeInt32Vector(_aidl_return);
@@ -328,14 +355,7 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = Piff(in_times);
-if (((status) != (android::OK))) {
-break;
-}
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
-break;
-}
+android::binder::Status _aidl_status(Piff(in_times));
 }
 break;
 case Call::TAKESABINDER:
@@ -350,12 +370,12 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = TakesABinder(in_f, &_aidl_return);
+android::binder::Status _aidl_status(TakesABinder(in_f, &_aidl_return));
+status = _aidl_status.writeToParcel(reply);
 if (((status) != (android::OK))) {
 break;
 }
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
+if (!_aidl_status.isOk()) {
 break;
 }
 status = reply->writeStrongBinder(IFooType::asBinder(_aidl_return));
@@ -377,12 +397,12 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = StringListMethod(in_input, &out_output, &_aidl_return);
+android::binder::Status _aidl_status(StringListMethod(in_input, &out_output, &_aidl_return));
+status = _aidl_status.writeToParcel(reply);
 if (((status) != (android::OK))) {
 break;
 }
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
+if (!_aidl_status.isOk()) {
 break;
 }
 status = reply->writeString16Vector(_aidl_return);
@@ -408,12 +428,12 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = BinderListMethod(in_input, &out_output, &_aidl_return);
+android::binder::Status _aidl_status(BinderListMethod(in_input, &out_output, &_aidl_return));
+status = _aidl_status.writeToParcel(reply);
 if (((status) != (android::OK))) {
 break;
 }
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
+if (!_aidl_status.isOk()) {
 break;
 }
 status = reply->writeStrongBinderVector(_aidl_return);
@@ -432,6 +452,9 @@
 }
 break;
 }
+if (status == android::UNEXPECTED_NULL) {
+status = android::binder::Status::fromExceptionCode(android::binder::Status::EX_NULL_POINTER).writeToParcel(reply);
+}
 return status;
 }
 
@@ -446,6 +469,7 @@
 
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
+#include <binder/Status.h>
 #include <cstdint>
 #include <foo/IFooType.h>
 #include <utils/String16.h>
@@ -459,11 +483,11 @@
 class IComplexTypeInterface : public android::IInterface {
 public:
 DECLARE_META_INTERFACE(ComplexTypeInterface);
-virtual android::status_t Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) = 0;
-virtual android::status_t Piff(int32_t times) = 0;
-virtual android::status_t TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) = 0;
-virtual android::status_t StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) = 0;
-virtual android::status_t BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) = 0;
+virtual android::binder::Status Send(const std::vector<int32_t>& goes_in, std::vector<double>* goes_in_and_out, std::vector<bool>* goes_out, std::vector<int32_t>* _aidl_return) = 0;
+virtual android::binder::Status Piff(int32_t times) = 0;
+virtual android::binder::Status TakesABinder(const android::sp<::foo::IFooType>& f, android::sp<::foo::IFooType>* _aidl_return) = 0;
+virtual android::binder::Status StringListMethod(const std::vector<android::String16>& input, std::vector<android::String16>* output, std::vector<android::String16>* _aidl_return) = 0;
+virtual android::binder::Status BinderListMethod(const std::vector<android::sp<::android::IBinder>>& input, std::vector<android::sp<::android::IBinder>>* output, std::vector<android::sp<::android::IBinder>>* _aidl_return) = 0;
 enum Call {
   SEND = android::IBinder::FIRST_CALL_TRANSACTION + 0,
   PIFF = android::IBinder::FIRST_CALL_TRANSACTION + 1,
diff --git a/tests/aidl_test_client.cpp b/tests/aidl_test_client.cpp
index 211d0fa..c3ae443 100644
--- a/tests/aidl_test_client.cpp
+++ b/tests/aidl_test_client.cpp
@@ -35,6 +35,7 @@
 // libbinder:
 using android::getService;
 using android::IBinder;
+using android::binder::Status;
 
 // generated
 using android::aidl::tests::ITestService;
@@ -62,12 +63,13 @@
 
 template <typename T>
 bool RepeatPrimitive(const sp<ITestService>& service,
-                     status_t(ITestService::*func)(T, T*),
+                     Status(ITestService::*func)(T, T*),
                      const T input) {
   T reply;
-  status_t status = (*service.*func)(input, &reply);
-  if (status != OK || input != reply) {
-    cerr << "Failed to repeat primitive. status=" << status << "." << endl;
+  Status status = (*service.*func)(input, &reply);
+  if (!status.isOk() || input != reply) {
+    cerr << "Failed to repeat primitive. status=" << status.toString8()
+         << "." << endl;
     return false;
   }
   return true;
@@ -93,11 +95,11 @@
   };
   for (const auto& input : inputs) {
     String16 reply;
-    status_t status = s->RepeatString(input, &reply);
-    if (status != OK || input != reply) {
+    Status status = s->RepeatString(input, &reply);
+    if (!status.isOk() || input != reply) {
       cerr << "Failed while requesting service to repeat String16=\""
            << String8(input).string()
-           << "\". Got status=" << status << endl;
+           << "\". Got status=" << status.toString8() << endl;
       return false;
     }
   }
@@ -106,15 +108,16 @@
 
 template <typename T>
 bool ReverseArray(const sp<ITestService>& service,
-                  status_t(ITestService::*func)(const vector<T>&,
-                                                vector<T>*,
-                                                vector<T>*),
+                  Status(ITestService::*func)(const vector<T>&,
+                                              vector<T>*,
+                                              vector<T>*),
                   vector<T> input) {
   vector<T> actual_reversed;
   vector<T> actual_repeated;
-  status_t status = (*service.*func)(input, &actual_repeated, &actual_reversed);
-  if (status != OK) {
-    cerr << "Failed to repeat array. status=" << status << "." << endl;
+  Status status = (*service.*func)(input, &actual_repeated, &actual_reversed);
+  if (!status.isOk()) {
+    cerr << "Failed to repeat array. status=" << status.toString8() << "."
+         << endl;
     return false;
   }
   if (input != actual_repeated) {
@@ -168,7 +171,7 @@
 }
 
 bool ConfirmReverseBinderLists(const sp<ITestService>& s) {
-  status_t status;
+  Status status;
   cout << "Confirming passing and returning List<T> works with binders." << endl;
 
   vector<String16> names = {
@@ -183,7 +186,7 @@
     sp<INamedCallback> got;
 
     status = s->GetOtherTestService(names[i], &got);
-    if (status != OK) {
+    if (!status.isOk()) {
       cerr << "Could not retrieve service for test." << endl;
       return false;
     }
@@ -195,6 +198,9 @@
   vector<sp<IBinder>> reversed;
 
   status = s->ReverseNamedCallbackList(input, &output, &reversed);
+  if (!status.isOk()) {
+    cerr << "Failed to reverse named callback list." << endl;
+  }
 
   if (output.size() != 3) {
     cerr << "ReverseNamedCallbackList gave repetition with wrong length." << endl;
@@ -212,7 +218,7 @@
         android::interface_cast<INamedCallback>(output[i]);
     status = named_callback->GetName(&ret);
 
-    if (status != OK) {
+    if (!status.isOk()) {
       cerr << "Could not query INamedCallback from output" << endl;
       return false;
     }
@@ -229,7 +235,7 @@
         android::interface_cast<INamedCallback>(reversed[i]);
     status = named_callback->GetName(&ret);
 
-    if (status != OK) {
+    if (!status.isOk()) {
       cerr << "Could not query INamedCallback from reversed output" << endl;
       return false;
     }
diff --git a/tests/aidl_test_service.cpp b/tests/aidl_test_service.cpp
index b41cac7..5c3d672 100644
--- a/tests/aidl_test_service.cpp
+++ b/tests/aidl_test_service.cpp
@@ -43,7 +43,6 @@
 using android::LooperCallback;
 using android::OK;
 using android::sp;
-using android::status_t;
 using android::String16;
 
 // libbinder:
@@ -53,6 +52,7 @@
 using android::IPCThreadState;
 using android::Parcel;
 using android::ProcessState;
+using android::binder::Status;
 
 // Generated code:
 using android::aidl::tests::BnTestService;
@@ -82,9 +82,9 @@
  public:
   NamedCallback(String16 name) : name_(name) {}
 
-  status_t GetName(String16* ret) {
+  Status GetName(String16* ret) {
     *ret = name_;
-    return OK;
+    return Status::ok();
   }
 
  private:
@@ -135,101 +135,101 @@
     ALOGI("Repeating token %s", token_str.str().c_str());
   }
 
-  status_t RepeatBoolean(bool token, bool* _aidl_return) override {
+  Status RepeatBoolean(bool token, bool* _aidl_return) override {
     LogRepeatedToken(token ? 1 : 0);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatByte(int8_t token, int8_t* _aidl_return) override {
+  Status RepeatByte(int8_t token, int8_t* _aidl_return) override {
     LogRepeatedToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatChar(char16_t token, char16_t* _aidl_return) override {
+  Status RepeatChar(char16_t token, char16_t* _aidl_return) override {
     LogRepeatedStringToken(String16(&token, 1));
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatInt(int32_t token, int32_t* _aidl_return) override {
+  Status RepeatInt(int32_t token, int32_t* _aidl_return) override {
     LogRepeatedToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatLong(int64_t token, int64_t* _aidl_return) override {
+  Status RepeatLong(int64_t token, int64_t* _aidl_return) override {
     LogRepeatedToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatFloat(float token, float* _aidl_return) override {
+  Status RepeatFloat(float token, float* _aidl_return) override {
     LogRepeatedToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatDouble(double token, double* _aidl_return) override {
+  Status RepeatDouble(double token, double* _aidl_return) override {
     LogRepeatedToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
-  status_t RepeatString(
+  Status RepeatString(
       const String16& token, String16* _aidl_return) override {
     LogRepeatedStringToken(token);
     *_aidl_return = token;
-    return OK;
+    return Status::ok();
   }
 
   template<typename T>
-  status_t ReverseArray(const vector<T>& input,
+  Status ReverseArray(const vector<T>& input,
                         vector<T>* repeated,
                         vector<T>* _aidl_return) {
     ALOGI("Reversing array of length %zu", input.size());
     *repeated = input;
     *_aidl_return = input;
     std::reverse(_aidl_return->begin(), _aidl_return->end());
-    return OK;
+    return Status::ok();
   }
 
-  status_t ReverseBoolean(const vector<bool>& input,
+  Status ReverseBoolean(const vector<bool>& input,
                           vector<bool>* repeated,
                           vector<bool>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseByte(const vector<int8_t>& input,
+  Status ReverseByte(const vector<int8_t>& input,
                        vector<int8_t>* repeated,
                        vector<int8_t>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseChar(const vector<char16_t>& input,
+  Status ReverseChar(const vector<char16_t>& input,
                        vector<char16_t>* repeated,
                        vector<char16_t>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseInt(const vector<int32_t>& input,
+  Status ReverseInt(const vector<int32_t>& input,
                       vector<int32_t>* repeated,
                       vector<int32_t>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseLong(const vector<int64_t>& input,
+  Status ReverseLong(const vector<int64_t>& input,
                        vector<int64_t>* repeated,
                        vector<int64_t>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseFloat(const vector<float>& input,
+  Status ReverseFloat(const vector<float>& input,
                         vector<float>* repeated,
                         vector<float>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseDouble(const vector<double>& input,
+  Status ReverseDouble(const vector<double>& input,
                          vector<double>* repeated,
                          vector<double>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
-  status_t ReverseString(const vector<String16>& input,
+  Status ReverseString(const vector<String16>& input,
                          vector<String16>* repeated,
                          vector<String16>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
 
-  status_t GetOtherTestService(const String16& name,
+  Status GetOtherTestService(const String16& name,
                                sp<INamedCallback>* returned_service) override {
     if (service_map_.find(name) == service_map_.end()) {
       sp<INamedCallback> new_item(new NamedCallback(name));
@@ -237,28 +237,28 @@
     }
 
     *returned_service = service_map_[name];
-    return OK;
+    return Status::ok();
   }
 
-  status_t VerifyName(const sp<INamedCallback>& service, const String16& name,
+  Status VerifyName(const sp<INamedCallback>& service, const String16& name,
                       bool* returned_value) override {
     String16 foundName;
-    status_t err = service->GetName(&foundName);
+    Status status = service->GetName(&foundName);
 
-    if (err == OK) {
+    if (status.isOk()) {
       *returned_value = foundName == name;
     }
 
-    return err;
+    return status;
   }
 
-  status_t ReverseStringList(const vector<String16>& input,
+  Status ReverseStringList(const vector<String16>& input,
                              vector<String16>* repeated,
                              vector<String16>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
   }
 
-  status_t ReverseNamedCallbackList(const vector<sp<IBinder>>& input,
+  Status ReverseNamedCallbackList(const vector<sp<IBinder>>& input,
                                     vector<sp<IBinder>>* repeated,
                                     vector<sp<IBinder>>* _aidl_return) override {
     return ReverseArray(input, repeated, _aidl_return);
diff --git a/tests/test_data_ping_responder.cpp b/tests/test_data_ping_responder.cpp
index 0225f8b..9b79c96 100644
--- a/tests/test_data_ping_responder.cpp
+++ b/tests/test_data_ping_responder.cpp
@@ -81,31 +81,37 @@
     : BpInterface<IPingResponder>(impl){
 }
 
-android::status_t BpPingResponder::Ping(int32_t token, int32_t* _aidl_return) {
+android::binder::Status BpPingResponder::Ping(int32_t token, int32_t* _aidl_return) {
 android::Parcel data;
 android::Parcel reply;
 android::status_t status;
+android::binder::Status _aidl_status;
 status = data.writeInterfaceToken(getInterfaceDescriptor());
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = data.writeInt32(token);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
 status = remote()->transact(IPingResponder::PING, data, &reply);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-if (reply.readExceptionCode()) {
-status = android::FAILED_TRANSACTION;
-return status;
+status = _aidl_status.readFromParcel(reply);
+if (((status) != (android::OK))) {
+goto error;
+}
+if (!_aidl_status.isOk()) {
+return _aidl_status;
 }
 status = reply.readInt32(_aidl_return);
 if (((status) != (android::OK))) {
-return status;
+goto error;
 }
-return status;
+error:
+_aidl_status.setFromStatusT(status);
+return _aidl_status;
 }
 
 }  // namespace os
@@ -133,12 +139,12 @@
 if (((status) != (android::OK))) {
 break;
 }
-status = Ping(in_token, &_aidl_return);
+android::binder::Status _aidl_status(Ping(in_token, &_aidl_return));
+status = _aidl_status.writeToParcel(reply);
 if (((status) != (android::OK))) {
 break;
 }
-status = reply->writeNoException();
-if (((status) != (android::OK))) {
+if (!_aidl_status.isOk()) {
 break;
 }
 status = reply->writeInt32(_aidl_return);
@@ -153,6 +159,9 @@
 }
 break;
 }
+if (status == android::UNEXPECTED_NULL) {
+status = android::binder::Status::fromExceptionCode(android::binder::Status::EX_NULL_POINTER).writeToParcel(reply);
+}
 return status;
 }
 
@@ -167,6 +176,7 @@
 
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
+#include <binder/Status.h>
 #include <cstdint>
 #include <utils/StrongPointer.h>
 
@@ -177,7 +187,7 @@
 class IPingResponder : public android::IInterface {
 public:
 DECLARE_META_INTERFACE(PingResponder);
-virtual android::status_t Ping(int32_t token, int32_t* _aidl_return) = 0;
+virtual android::binder::Status Ping(int32_t token, int32_t* _aidl_return) = 0;
 enum Call {
   PING = android::IBinder::FIRST_CALL_TRANSACTION + 0,
 };
@@ -206,7 +216,7 @@
 public:
 explicit BpPingResponder(const android::sp<android::IBinder>& impl);
 virtual ~BpPingResponder() = default;
-android::status_t Ping(int32_t token, int32_t* _aidl_return) override;
+android::binder::Status Ping(int32_t token, int32_t* _aidl_return) override;
 };  // class BpPingResponder
 
 }  // namespace os