Ensure Binder finalizer handles partially initialized instances.

If the Binder is allocated but its constructor does not run for some
reason, then Binder.init() will not be called.  Since the object was
allocated, it is still eligible for finalization.  Eventually when
the finalizer runs and calls Binder.destroy(), it will have a NULL
binder holder pointer.  Previously this would cause Binder.destroy()
to attempt to decrement a reference count on a NULL pointer.

Now we check and ignore the binder if it does not have a valid
holder pointer.

Bug: b/2533956
Change-Id: Ifc2729b2f2abe8bceea5a0645ae0a4c1575b7846
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 627fcbf..5182a77 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -590,9 +590,19 @@
 {
     JavaBBinderHolder* jbh = (JavaBBinderHolder*)
         env->GetIntField(clazz, gBinderOffsets.mObject);
-    env->SetIntField(clazz, gBinderOffsets.mObject, 0);
-    LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh);
-    jbh->decStrong(clazz);
+    if (jbh != NULL) {
+        env->SetIntField(clazz, gBinderOffsets.mObject, 0);
+        LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh);
+        jbh->decStrong(clazz);
+    } else {
+        // Encountering an uninitialized binder is harmless.  All it means is that
+        // the Binder was only partially initialized when its finalizer ran and called
+        // destroy().  The Binder could be partially initialized for several reasons.
+        // For example, a Binder subclass constructor might have thrown an exception before
+        // it could delegate to its superclass's constructor.  Consequently init() would
+        // not have been called and the holder pointer would remain NULL.
+        LOGV("Java Binder %p: ignoring uninitialized binder", clazz);
+    }
 }
 
 // ----------------------------------------------------------------------------