Merge "libbinder_ndk: @file, @addtogroup"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..f8f0265
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,3 @@
+[Hook Scripts]
+owners_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "OWNERS$"
+installd_hook = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} "^cmds/installd/"
diff --git a/cmds/installd/OWNERS b/cmds/installd/OWNERS
new file mode 100644
index 0000000..50440f1
--- /dev/null
+++ b/cmds/installd/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+calin@google.com
+agampe@google.com
+jsharkey@android.com
+toddke@google.com
+ngeoffray@google.com
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0fd2dd4..03a411d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1692,15 +1692,12 @@
             *dexopt_needed_out = NO_DEXOPT_NEEDED; return true;
         case 1:  // dexoptanalyzer: dex2oat_from_scratch
             *dexopt_needed_out = DEX2OAT_FROM_SCRATCH; return true;
-        case 5:  // dexoptanalyzer: dex2oat_for_bootimage_odex
+        case 4:  // dexoptanalyzer: dex2oat_for_bootimage_odex
             *dexopt_needed_out = -DEX2OAT_FOR_BOOT_IMAGE; return true;
-        case 6:  // dexoptanalyzer: dex2oat_for_filter_odex
+        case 5:  // dexoptanalyzer: dex2oat_for_filter_odex
             *dexopt_needed_out = -DEX2OAT_FOR_FILTER; return true;
-        case 7:  // dexoptanalyzer: dex2oat_for_relocation_odex
-            *dexopt_needed_out = -DEX2OAT_FOR_RELOCATION; return true;
         case 2:  // dexoptanalyzer: dex2oat_for_bootimage_oat
         case 3:  // dexoptanalyzer: dex2oat_for_filter_oat
-        case 4:  // dexoptanalyzer: dex2oat_for_relocation_oat
             *error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
                                       " Expected odex file status for secondary dex %s"
                                       " : dexoptanalyzer result=%d",
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index bb6fab3..0db11e1 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -31,7 +31,6 @@
 static constexpr int DEX2OAT_FROM_SCRATCH        = 1;
 static constexpr int DEX2OAT_FOR_BOOT_IMAGE      = 2;
 static constexpr int DEX2OAT_FOR_FILTER          = 3;
-static constexpr int DEX2OAT_FOR_RELOCATION      = 4;
 
 // Clear the reference profile identified by the given profile name.
 bool clear_primary_reference_profile(const std::string& pkgname, const std::string& profile_name);
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index d516eb1..857bbf9 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -189,7 +189,7 @@
                 // them out without going through the buffer.
                 
                 // Slurp up all of the lines.
-                const char* lastLine = txt+1;
+                const char* lastLine = txt;
                 while (txt < end) {
                     if (*txt++ == '\n') lastLine = txt;
                 }
diff --git a/libs/binder/ndk/AIBinder.cpp b/libs/binder/ndk/AIBinder.cpp
index d0ce98d..2219f8e 100644
--- a/libs/binder/ndk/AIBinder.cpp
+++ b/libs/binder/ndk/AIBinder.cpp
@@ -28,14 +28,29 @@
 using ::android::String16;
 using ::android::wp;
 
+namespace ABBinderTag {
+
+static const void* kId = "ABBinder";
+static void* kValue = static_cast<void*>(new bool{true});
+void cleanId(const void* /*id*/, void* /*obj*/, void* /*cookie*/){/* do nothing */};
+
+static void attach(const sp<IBinder>& binder) {
+    binder->attachObject(kId, kValue, nullptr /*cookie*/, cleanId);
+}
+static bool has(const sp<IBinder>& binder) {
+    return binder != nullptr && binder->findObject(kId) == kValue;
+}
+
+} // namespace ABBinderTag
+
 AIBinder::AIBinder(const AIBinder_Class* clazz) : mClazz(clazz) {}
 AIBinder::~AIBinder() {}
 
-sp<AIBinder> AIBinder::associateClass(const AIBinder_Class* clazz) {
+bool AIBinder::associateClass(const AIBinder_Class* clazz) {
     using ::android::String8;
 
-    if (clazz == nullptr) return nullptr;
-    if (mClazz == clazz) return this;
+    if (clazz == nullptr) return false;
+    if (mClazz == clazz) return true;
 
     String8 newDescriptor(clazz->getInterfaceDescriptor());
 
@@ -45,42 +60,31 @@
             LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
                        << "' match during associateClass, but they are different class objects. "
                           "Class descriptor collision?";
-            return nullptr;
+        } else {
+            LOG(ERROR) << __func__
+                       << ": Class cannot be associated on object which already has a class. "
+                          "Trying to associate to '"
+                       << newDescriptor.c_str() << "' but already set to '"
+                       << currentDescriptor.c_str() << "'.";
         }
 
-        LOG(ERROR) << __func__
-                   << ": Class cannot be associated on object which already has a class. Trying to "
-                      "associate to '"
-                   << newDescriptor.c_str() << "' but already set to '" << currentDescriptor.c_str()
-                   << "'.";
-        return nullptr;
+        // always a failure because we know mClazz != clazz
+        return false;
     }
 
+    CHECK(asABpBinder() != nullptr); // ABBinder always has a descriptor
+
     String8 descriptor(getBinder()->getInterfaceDescriptor());
     if (descriptor != newDescriptor) {
         LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor.c_str()
                    << "' but descriptor is actually '" << descriptor.c_str() << "'.";
-        return nullptr;
+        return false;
     }
 
-    // The descriptor matches, so if it is local, this is guaranteed to be the libbinder_ndk class.
-    // An error here can occur if there is a conflict between descriptors (two unrelated classes
-    // define the same descriptor), but this should never happen.
-
-    // if this is a local ABBinder, mClazz should be non-null
-    CHECK(asABBinder() == nullptr);
-    CHECK(asABpBinder() != nullptr);
-
-    if (!isRemote()) {
-        // ABpBinder but proxy to a local object. Therefore that local object must be an ABBinder.
-        ABBinder* binder = static_cast<ABBinder*>(getBinder().get());
-        return binder;
-    }
-
-    // This is a remote object
+    // if this is a local object, it's not one known to libbinder_ndk
     mClazz = clazz;
 
-    return this;
+    return true;
 }
 
 ABBinder::ABBinder(const AIBinder_Class* clazz, void* userData)
@@ -111,24 +115,45 @@
     }
 }
 
-ABpBinder::ABpBinder(::android::sp<::android::IBinder> binder)
+ABpBinder::ABpBinder(const ::android::sp<::android::IBinder>& binder)
       : AIBinder(nullptr /*clazz*/), BpRefBase(binder) {
     CHECK(binder != nullptr);
 }
 ABpBinder::~ABpBinder() {}
 
+sp<AIBinder> ABpBinder::fromBinder(const ::android::sp<::android::IBinder>& binder) {
+    if (binder == nullptr) {
+        return nullptr;
+    }
+    if (ABBinderTag::has(binder)) {
+        return static_cast<ABBinder*>(binder.get());
+    }
+    return new ABpBinder(binder);
+}
+
 struct AIBinder_Weak {
     wp<AIBinder> binder;
 };
 AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder) {
-    if (binder == nullptr) return nullptr;
+    if (binder == nullptr) {
+        return nullptr;
+    }
+
     return new AIBinder_Weak{wp<AIBinder>(binder)};
 }
-void AIBinder_Weak_delete(AIBinder_Weak* weakBinder) {
-    delete weakBinder;
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder) {
+    if (weakBinder == nullptr) {
+        return;
+    }
+
+    delete *weakBinder;
+    *weakBinder = nullptr;
 }
 AIBinder* AIBinder_Weak_promote(AIBinder_Weak* weakBinder) {
-    if (weakBinder == nullptr) return nullptr;
+    if (weakBinder == nullptr) {
+        return nullptr;
+    }
+
     sp<AIBinder> binder = weakBinder->binder.promote();
     AIBinder_incStrong(binder.get());
     return binder.get();
@@ -162,12 +187,14 @@
 
     void* userData = clazz->onCreate(args);
 
-    AIBinder* ret = new ABBinder(clazz, userData);
-    AIBinder_incStrong(ret);
-    return ret;
+    sp<AIBinder> ret = new ABBinder(clazz, userData);
+    ABBinderTag::attach(ret->getBinder());
+
+    AIBinder_incStrong(ret.get());
+    return ret.get();
 }
 
-bool AIBinder_isRemote(AIBinder* binder) {
+bool AIBinder_isRemote(const AIBinder* binder) {
     if (binder == nullptr) {
         return true;
     }
@@ -175,6 +202,22 @@
     return binder->isRemote();
 }
 
+bool AIBinder_isAlive(const AIBinder* binder) {
+    if (binder == nullptr) {
+        return false;
+    }
+
+    return const_cast<AIBinder*>(binder)->getBinder()->isBinderAlive();
+}
+
+binder_status_t AIBinder_ping(AIBinder* binder) {
+    if (binder == nullptr) {
+        return EX_NULL_POINTER;
+    }
+
+    return binder->getBinder()->pingBinder();
+}
+
 void AIBinder_incStrong(AIBinder* binder) {
     if (binder == nullptr) {
         LOG(ERROR) << __func__ << ": on null binder";
@@ -200,23 +243,12 @@
     return binder->getStrongCount();
 }
 
-void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz) {
-    if (binder == nullptr || *binder == nullptr) {
-        return;
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz) {
+    if (binder == nullptr) {
+        return false;
     }
 
-    sp<AIBinder> result = (*binder)->associateClass(clazz);
-
-    // This function takes one refcount of 'binder' and delivers one refcount of 'result' to the
-    // callee. First we give the callee their refcount and then take it away from binder. This is
-    // done in this order in order to handle the case that the result and the binder are the same
-    // object.
-    if (result != nullptr) {
-        AIBinder_incStrong(result.get());
-    }
-    AIBinder_decStrong(*binder);
-
-    *binder = result.get(); // Maybe no-op
+    return binder->associateClass(clazz);
 }
 
 const AIBinder_Class* AIBinder_getClass(AIBinder* binder) {
@@ -253,6 +285,13 @@
         return EX_ILLEGAL_STATE;
     }
 
+    if (!binder->isRemote()) {
+        LOG(WARNING) << "A binder object at " << binder
+                     << " is being transacted on, however, this object is in the same process as "
+                        "its proxy. Transacting with this binder is expensive compared to just "
+                        "calling the corresponding functionality in the same process.";
+    }
+
     *in = new AParcel(binder);
     binder_status_t status = (**in)->writeInterfaceToken(clazz->getInterfaceDescriptor());
     if (status != EX_NONE) {
@@ -263,12 +302,6 @@
     return status;
 }
 
-using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
-static void destroy_parcel(AParcel** parcel) {
-    delete *parcel;
-    *parcel = nullptr;
-}
-
 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
                                   AParcel** out, binder_flags_t flags) {
     if (in == nullptr) {
@@ -276,9 +309,10 @@
         return EX_NULL_POINTER;
     }
 
+    using AutoParcelDestroyer = std::unique_ptr<AParcel*, void (*)(AParcel**)>;
     // This object is the input to the transaction. This function takes ownership of it and deletes
     // it.
-    AutoParcelDestroyer forIn(in, destroy_parcel);
+    AutoParcelDestroyer forIn(in, AParcel_delete);
 
     if (!isUserCommand(code)) {
         LOG(ERROR) << __func__ << ": Only user-defined transactions can be made from the NDK.";
@@ -313,33 +347,3 @@
 
     return parcelStatus;
 }
-
-binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out) {
-    if (out == nullptr) {
-        LOG(ERROR) << __func__ << ": requires non-null out parameter";
-        return EX_NULL_POINTER;
-    }
-
-    // This object is the input to the transaction. This function takes ownership of it and deletes
-    // it.
-    AutoParcelDestroyer forOut(out, destroy_parcel);
-
-    if (binder == nullptr || *out == nullptr) {
-        LOG(ERROR) << __func__ << ": requires non-null parameters.";
-        return EX_NULL_POINTER;
-    }
-
-    if ((*out)->getBinder() != binder) {
-        LOG(ERROR) << __func__ << ": parcel is associated with binder object " << binder
-                   << " but called with " << (*out)->getBinder();
-        return EX_ILLEGAL_STATE;
-    }
-
-    if ((**out)->dataAvail() != 0) {
-        LOG(ERROR) << __func__
-                   << ": Only part of this transaction was read. There is remaining data left.";
-        return EX_ILLEGAL_STATE;
-    }
-
-    return EX_NONE;
-}
diff --git a/libs/binder/ndk/AIBinder_internal.h b/libs/binder/ndk/AIBinder_internal.h
index d44b937..23949bb 100644
--- a/libs/binder/ndk/AIBinder_internal.h
+++ b/libs/binder/ndk/AIBinder_internal.h
@@ -35,23 +35,16 @@
     AIBinder(const AIBinder_Class* clazz);
     virtual ~AIBinder();
 
-    // This returns an AIBinder object with this class associated. If the class is already
-    // associated, 'this' will be returned. If there is a local AIBinder implementation, that will
-    // be returned. If this is a remote object, the class will be associated and this will be ready
-    // to be used for transactions.
-    ::android::sp<AIBinder> associateClass(const AIBinder_Class* clazz);
+    bool associateClass(const AIBinder_Class* clazz);
     const AIBinder_Class* getClass() const { return mClazz; }
 
-    // This does not create the binder if it does not exist in the process.
     virtual ::android::sp<::android::IBinder> getBinder() = 0;
     virtual ABBinder* asABBinder() { return nullptr; }
     virtual ABpBinder* asABpBinder() { return nullptr; }
 
-    bool isRemote() {
-        auto binder = getBinder();
-        // if the binder is nullptr, then it is a local object which hasn't been sent out of process
-        // yet.
-        return binder != nullptr && binder->remoteBinder() != nullptr;
+    bool isRemote() const {
+        ::android::sp<::android::IBinder> binder = const_cast<AIBinder*>(this)->getBinder();
+        return binder->remoteBinder() != nullptr;
     }
 
 private:
@@ -63,7 +56,6 @@
 
 // This is a local AIBinder object with a known class.
 struct ABBinder : public AIBinder, public ::android::BBinder {
-    ABBinder(const AIBinder_Class* clazz, void* userData);
     virtual ~ABBinder();
 
     void* getUserData() { return mUserData; }
@@ -76,6 +68,11 @@
                                ::android::Parcel* reply, binder_flags_t flags) override;
 
 private:
+    ABBinder(const AIBinder_Class* clazz, void* userData);
+
+    // only thing that should create an ABBinder
+    friend AIBinder* AIBinder_new(const AIBinder_Class*, void*);
+
     // Can contain implementation if this is a local binder. This can still be nullptr for a local
     // binder. If it is nullptr, the implication is the implementation state is entirely external to
     // this object and the functionality provided in the AIBinder_Class is sufficient.
@@ -85,11 +82,15 @@
 // This binder object may be remote or local (even though it is 'Bp'). It is not yet associated with
 // a class.
 struct ABpBinder : public AIBinder, public ::android::BpRefBase {
-    ABpBinder(::android::sp<::android::IBinder> binder);
+    static ::android::sp<AIBinder> fromBinder(const ::android::sp<::android::IBinder>& binder);
+
     virtual ~ABpBinder();
 
     ::android::sp<::android::IBinder> getBinder() override { return remote(); }
     ABpBinder* asABpBinder() override { return this; }
+
+private:
+    ABpBinder(const ::android::sp<::android::IBinder>& binder);
 };
 
 struct AIBinder_Class {
diff --git a/libs/binder/ndk/AParcel.cpp b/libs/binder/ndk/AParcel.cpp
index b63b138..93384d6 100644
--- a/libs/binder/ndk/AParcel.cpp
+++ b/libs/binder/ndk/AParcel.cpp
@@ -25,6 +25,15 @@
 using ::android::Parcel;
 using ::android::sp;
 
+void AParcel_delete(AParcel** parcel) {
+    if (parcel == nullptr) {
+        return;
+    }
+
+    delete *parcel;
+    *parcel = nullptr;
+}
+
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
     return (*parcel)->writeStrongBinder(binder->getBinder());
 }
@@ -34,8 +43,9 @@
     if (status != EX_NONE) {
         return status;
     }
-    *binder = new ABpBinder(readBinder);
-    AIBinder_incStrong(*binder);
+    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    AIBinder_incStrong(ret.get());
+    *binder = ret.get();
     return status;
 }
 binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
@@ -44,8 +54,9 @@
     if (status != EX_NONE) {
         return status;
     }
-    *binder = new ABpBinder(readBinder);
-    AIBinder_incStrong(*binder);
+    sp<AIBinder> ret = ABpBinder::fromBinder(readBinder);
+    AIBinder_incStrong(ret.get());
+    *binder = ret.get();
     return status;
 }
 
diff --git a/libs/binder/ndk/AServiceManager.cpp b/libs/binder/ndk/AServiceManager.cpp
index f61b914..3979945 100644
--- a/libs/binder/ndk/AServiceManager.cpp
+++ b/libs/binder/ndk/AServiceManager.cpp
@@ -41,7 +41,7 @@
     sp<IServiceManager> sm = defaultServiceManager();
     sp<IBinder> binder = sm->getService(String16(instance));
 
-    AIBinder* ret = new ABpBinder(binder);
-    AIBinder_incStrong(ret);
-    return ret;
+    sp<AIBinder> ret = ABpBinder::fromBinder(binder);
+    AIBinder_incStrong(ret.get());
+    return ret.get();
 }
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 0bd4b8c..65bc5a5 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -154,7 +154,23 @@
 /**
  * If this is hosted in a process other than the current one.
  */
-bool AIBinder_isRemote(AIBinder* binder);
+bool AIBinder_isRemote(const AIBinder* binder);
+
+/**
+ * If this binder is known to be alive. This will not send a transaction to a remote process and
+ * returns a result based on the last known information. That is, whenever a transaction is made,
+ * this is automatically updated to reflect the current alive status of this binder. This will be
+ * updated as the result of a transaction made using AIBinder_transact, but it will also be updated
+ * based on the results of bookkeeping or other transactions made internally.
+ */
+bool AIBinder_isAlive(const AIBinder* binder);
+
+/**
+ * Built-in transaction for all binder objects. This sends a transaction which will immediately
+ * return. Usually this is used to make sure that a binder is alive, as a placeholder call, or as a
+ * sanity check.
+ */
+binder_status_t AIBinder_ping(AIBinder* binder);
 
 /**
  * This can only be called if a strong reference to this object already exists in process.
@@ -177,13 +193,12 @@
  * However, if an object is just intended to be passed through to another process or used as a
  * handle this need not be called.
  *
- * The binder parameter may or may not be updated. If it is updated, the ownership of the original
- * object is transferred to the new object. If the class association fails, ownership of the binder
- * is lost, and it is set to nullptr.
+ * This returns true if the class association succeeds. If it fails, no change is made to the
+ * binder object.
  */
-void AIBinder_associateClass(AIBinder** binder, const AIBinder_Class* clazz);
+bool AIBinder_associateClass(AIBinder* binder, const AIBinder_Class* clazz);
 
-/*
+/**
  * Returns the class that this binder was constructed with or associated with.
  */
 const AIBinder_Class* AIBinder_getClass(AIBinder* binder);
@@ -197,10 +212,9 @@
 /**
  * A transaction is a series of calls to these functions which looks this
  * - call AIBinder_prepareTransaction
- * - fill out parcel with in parameters (lifetime of the 'in' variable)
+ * - fill out the in parcel with parameters (lifetime of the 'in' variable)
  * - call AIBinder_transact
- * - fill out parcel with out parameters (lifetime of the 'out' variable)
- * - call AIBinder_finalizeTransaction
+ * - read results from the out parcel (lifetime of the 'out' variable)
  */
 
 /**
@@ -211,7 +225,10 @@
  * can be avoided. This AIBinder must be either built with a class or associated with a class before
  * using this API.
  *
- * This does not affect the ownership of binder.
+ * This does not affect the ownership of binder. When this function succeeds, the in parcel's
+ * ownership is passed to the caller. At this point, the parcel can be filled out and passed to
+ * AIBinder_transact. Alternatively, if there is an error while filling out the parcel, it can be
+ * deleted with AParcel_delete.
  */
 binder_status_t AIBinder_prepareTransaction(AIBinder* binder, AParcel** in);
 
@@ -224,29 +241,22 @@
  * remote process has processed the transaction, and the out parcel will contain the output data
  * from transaction.
  *
- * This does not affect the ownership of binder.
+ * This does not affect the ownership of binder. The out parcel's ownership is passed to the caller
+ * and must be released with AParcel_delete when finished reading.
  */
 binder_status_t AIBinder_transact(AIBinder* binder, transaction_code_t code, AParcel** in,
                                   AParcel** out, binder_flags_t flags);
 
 /**
- * This takes ownership of the out parcel and automatically deletes it. Additional checks for
- * security or debugging maybe performed internally.
- *
- * This does not affect the ownership of binder.
- */
-binder_status_t AIBinder_finalizeTransaction(AIBinder* binder, AParcel** out);
-
-/*
  * This does not take any ownership of the input binder, but it can be used to retrieve it if
  * something else in some process still holds a reference to it.
  */
 __attribute__((warn_unused_result)) AIBinder_Weak* AIBinder_Weak_new(AIBinder* binder);
 
-/*
+/**
  * Deletes the weak reference. This will have no impact on the lifetime of the binder.
  */
-void AIBinder_Weak_delete(AIBinder_Weak* weakBinder);
+void AIBinder_Weak_delete(AIBinder_Weak** weakBinder);
 
 /**
  * If promotion succeeds, result will have one strong refcount added to it. Otherwise, this returns
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index 75ac4ff..e871ed1 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -45,6 +45,11 @@
 typedef struct AParcel AParcel;
 
 /**
+ * Cleans up a parcel and sets it to nullptr.
+ */
+void AParcel_delete(AParcel** parcel);
+
+/**
  * Writes an AIBinder to the next location in a non-null parcel. Can be null.
  */
 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder);
diff --git a/libs/binder/ndk/test/iface.cpp b/libs/binder/ndk/test/iface.cpp
index eed09f0..a1aa0fa 100644
--- a/libs/binder/ndk/test/iface.cpp
+++ b/libs/binder/ndk/test/iface.cpp
@@ -81,7 +81,8 @@
         int32_t out;
         CHECK(EX_NONE == AParcel_readInt32(parcelOut, &out));
 
-        CHECK(EX_NONE == AIBinder_finalizeTransaction(mBinder, &parcelOut));
+        AParcel_delete(&parcelOut);
+
         return out;
     }
 
@@ -91,7 +92,7 @@
 };
 
 IFoo::~IFoo() {
-    AIBinder_Weak_delete(mWeakBinder);
+    AIBinder_Weak_delete(&mWeakBinder);
 }
 
 binder_status_t IFoo::addService(const char* instance) {
@@ -105,7 +106,7 @@
         // or one strong refcount here
         binder = AIBinder_new(IFoo::kClass, static_cast<void*>(new IFoo_Class_Data{this}));
         if (mWeakBinder != nullptr) {
-            AIBinder_Weak_delete(mWeakBinder);
+            AIBinder_Weak_delete(&mWeakBinder);
         }
         mWeakBinder = AIBinder_Weak_new(binder);
     }
@@ -118,12 +119,15 @@
 
 sp<IFoo> IFoo::getService(const char* instance) {
     AIBinder* binder = AServiceManager_getService(instance); // maybe nullptr
-    AIBinder_associateClass(&binder, IFoo::kClass);
-
     if (binder == nullptr) {
         return nullptr;
     }
 
+    if (!AIBinder_associateClass(binder, IFoo::kClass)) {
+        AIBinder_decStrong(binder);
+        return nullptr;
+    }
+
     if (AIBinder_isRemote(binder)) {
         sp<IFoo> ret = new BpFoo(binder); // takes ownership of binder
         return ret;
diff --git a/libs/binder/ndk/test/main_client.cpp b/libs/binder/ndk/test/main_client.cpp
index 7c53e51..967789f 100644
--- a/libs/binder/ndk/test/main_client.cpp
+++ b/libs/binder/ndk/test/main_client.cpp
@@ -38,6 +38,10 @@
 TEST(NdkBinder, RetrieveNonNdkService) {
     AIBinder* binder = AServiceManager_getService(kExistingNonNdkService);
     ASSERT_NE(nullptr, binder);
+    EXPECT_TRUE(AIBinder_isRemote(binder));
+    EXPECT_TRUE(AIBinder_isAlive(binder));
+    EXPECT_EQ(EX_NONE, AIBinder_ping(binder));
+
     AIBinder_decStrong(binder);
 }
 
diff --git a/libs/binder/tests/binderTextOutputTest.cpp b/libs/binder/tests/binderTextOutputTest.cpp
index f6dd22d..ce99f59 100644
--- a/libs/binder/tests/binderTextOutputTest.cpp
+++ b/libs/binder/tests/binderTextOutputTest.cpp
@@ -28,15 +28,14 @@
 #include <binder/TextOutput.h>
 #include <binder/Debug.h>
 
-static void CheckMessage(const CapturedStderr& cap,
+static void CheckMessage(CapturedStderr& cap,
                          const char* expected,
                          bool singleline) {
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
+    cap.Stop();
+    std::string output = cap.str();
     if (singleline)
         output.erase(std::remove(output.begin(), output.end(), '\n'));
-    ASSERT_STREQ(output.c_str(), expected);
+    ASSERT_EQ(output, expected);
 }
 
 #define CHECK_LOG_(input, expect, singleline)    \
@@ -60,28 +59,22 @@
 TEST(TextOutput, HandlesStdEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << std::endl;
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandlesCEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << "\n";
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandlesAndroidEndl) {
     CapturedStderr cap;
     android::aerr << "foobar" << android::endl;
-    std::string output;
-    ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
-    android::base::ReadFdToString(cap.fd(), &output);
-    ASSERT_STREQ(output.c_str(), "foobar\n");
+    cap.Stop();
+    ASSERT_EQ(cap.str(), "foobar\n");
 }
 
 TEST(TextOutput, HandleEmptyString) {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fda7906..f04bd17 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -622,6 +622,9 @@
     const auto& viewport = displayDevice->getViewport();
     Region visible = tr.transform(visibleRegion.intersect(viewport));
     auto hwcId = displayDevice->getHwcDisplayId();
+    if (!hasHwcLayer(hwcId)) {
+        return;
+    }
     auto& hwcInfo = getBE().mHwcLayers[hwcId];
     auto& hwcLayer = hwcInfo.layer;
     auto error = hwcLayer->setVisibleRegion(visible);
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 512564c..ff957c0 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -66,6 +66,9 @@
     const auto& viewport = displayDevice->getViewport();
     Region visible = tr.transform(visibleRegion.intersect(viewport));
     auto hwcId = displayDevice->getHwcDisplayId();
+    if (!hasHwcLayer(hwcId)) {
+        return;
+    }
     auto& hwcInfo = getBE().mHwcLayers[hwcId];
     auto& hwcLayer = hwcInfo.layer;
     auto error = hwcLayer->setVisibleRegion(visible);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2595ec1..1dc3f4c 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -486,6 +486,9 @@
 void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z)
 {
     const auto hwcId = displayDevice->getHwcDisplayId();
+    if (!hasHwcLayer(hwcId)) {
+        return;
+    }
     auto& hwcInfo = getBE().mHwcLayers[hwcId];
 
     // enable this layer
@@ -1977,6 +1980,9 @@
 }
 
 void Layer::writeToProto(LayerProto* layerInfo, int32_t hwcId) {
+    if (!hasHwcLayer(hwcId)) {
+        return;
+    }
     writeToProto(layerInfo, LayerVector::StateSet::Drawing);
 
     const auto& hwcInfo = getBE().mHwcLayers.at(hwcId);