Merge Android Pie into master

Bug: 112104996
Change-Id: Iadbb695461201d8122ab0965a1ebde9f2584e432
diff --git a/Android.bp b/Android.bp
index 28da528..fee5417 100644
--- a/Android.bp
+++ b/Android.bp
@@ -16,8 +16,8 @@
     "vts/performance",
 ]
 
-cc_library {
-    name: "libhwbinder",
+cc_defaults {
+    name: "libhwbinder_defaults",
     shared_libs: [
         "libbase",
         "liblog",
@@ -65,3 +65,44 @@
         "-Werror",
     ],
 }
+
+cc_library {
+    name: "libhwbinder",
+    defaults: [
+        "libhwbinder_defaults",
+        "hwbinder_pgo",
+        "hwbinder_lto"
+    ],
+}
+
+// Explicitly provide a no lto, no PGO variant, to workaround the issue that we
+// can't detect non-lto users of the module in Android.mk.
+// http://b/77320844
+cc_library {
+    name: "libhwbinder_noltopgo",
+    defaults: [
+        "libhwbinder_defaults",
+    ],
+}
+
+// Provide pgo property to build hwbinder with PGO
+cc_defaults {
+    name: "hwbinder_pgo",
+    pgo: {
+        instrumentation: true,
+        profile_file: "hwbinder/hwbinder.profdata",
+        benchmarks: ["hwbinder"],
+        enable_profile_use: true,
+    },
+}
+// Provide lto property to build hwbinder with LTO
+cc_defaults {
+    name: "hwbinder_lto",
+    target: {
+        android: {
+            lto: {
+                thin: true,
+            },
+        },
+    },
+}
diff --git a/BpHwBinder.cpp b/BpHwBinder.cpp
index bd395a9..223f854 100644
--- a/BpHwBinder.cpp
+++ b/BpHwBinder.cpp
@@ -96,7 +96,7 @@
     ALOGV("Creating BpHwBinder %p handle %d\n", this, mHandle);
 
     extendObjectLifetime(OBJECT_LIFETIME_WEAK);
-    IPCThreadState::self()->incWeakHandle(handle);
+    IPCThreadState::self()->incWeakHandle(handle, this);
 }
 
 status_t BpHwBinder::transact(
@@ -282,7 +282,7 @@
 {
     ALOGV("onFirstRef BpHwBinder %p handle %d\n", this, mHandle);
     IPCThreadState* ipc = IPCThreadState::self();
-    if (ipc) ipc->incStrongHandle(mHandle);
+    if (ipc) ipc->incStrongHandle(mHandle, this);
 }
 
 void BpHwBinder::onLastStrongRef(const void* /*id*/)
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index 604210f..b275a7e 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -401,6 +401,15 @@
     if (mProcess->mDriverFD <= 0)
         return;
     talkWithDriver(false);
+    // The flush could have caused post-write refcount decrements to have
+    // been executed, which in turn could result in BC_RELEASE/BC_DECREFS
+    // being queued in mOut. So flush again, if we need to.
+    if (mOut.dataSize() > 0) {
+        talkWithDriver(false);
+    }
+    if (mOut.dataSize() > 0) {
+        ALOGW("mOut.dataSize() > 0 after flushCommands()");
+    }
 }
 
 void IPCThreadState::blockUntilThreadAvailable()
@@ -442,12 +451,15 @@
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount--;
-        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads && mProcess->mMaxThreads > 1 &&
+        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
             mProcess->mStarvationStartTimeMs != 0) {
             int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
             if (starvationTimeMs > 100) {
-                ALOGW("All binder threads in pool (%zu threads) busy for %" PRId64 " ms",
-                      mProcess->mMaxThreads, starvationTimeMs);
+                // If there is only a single-threaded client, nobody would be blocked
+                // on this, and it's not really starvation. (see b/37647467)
+                ALOGW("All binder threads in pool (%zu threads) busy for %" PRId64 " ms%s",
+                      mProcess->mMaxThreads, starvationTimeMs,
+                      mProcess->mMaxThreads > 1 ? "" : " (may be a false alarm)");
             }
             mProcess->mStarvationStartTimeMs = 0;
         }
@@ -503,6 +515,27 @@
     }
 }
 
+void IPCThreadState::processPostWriteDerefs()
+{
+    /*
+     * libhwbinder has a flushCommands() in the BpHwBinder destructor,
+     * which makes this function (potentially) reentrant.
+     * New entries shouldn't be added though, so just iterating until empty
+     * should be safe.
+     */
+    while (mPostWriteWeakDerefs.size() > 0) {
+        RefBase::weakref_type* refs = mPostWriteWeakDerefs[0];
+        mPostWriteWeakDerefs.removeAt(0);
+        refs->decWeak(mProcess.get());
+    }
+
+    while (mPostWriteStrongDerefs.size() > 0) {
+        RefBase* obj = mPostWriteStrongDerefs[0];
+        mPostWriteStrongDerefs.removeAt(0);
+        obj->decStrong(mProcess.get());
+    }
+}
+
 void IPCThreadState::joinThreadPool(bool isMain)
 {
     LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
@@ -635,11 +668,14 @@
     return err;
 }
 
-void IPCThreadState::incStrongHandle(int32_t handle)
+void IPCThreadState::incStrongHandle(int32_t handle, BpHwBinder *proxy)
 {
     LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle);
     mOut.writeInt32(BC_ACQUIRE);
     mOut.writeInt32(handle);
+    // Create a temp reference until the driver has handled this command.
+    proxy->incStrong(mProcess.get());
+    mPostWriteStrongDerefs.push(proxy);
 }
 
 void IPCThreadState::decStrongHandle(int32_t handle)
@@ -649,11 +685,14 @@
     mOut.writeInt32(handle);
 }
 
-void IPCThreadState::incWeakHandle(int32_t handle)
+void IPCThreadState::incWeakHandle(int32_t handle, BpHwBinder *proxy)
 {
     LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle);
     mOut.writeInt32(BC_INCREFS);
     mOut.writeInt32(handle);
+    // Create a temp reference until the driver has handled this command.
+    proxy->getWeakRefs()->incWeak(mProcess.get());
+    mPostWriteWeakDerefs.push(proxy->getWeakRefs());
 }
 
 void IPCThreadState::decWeakHandle(int32_t handle)
@@ -909,8 +948,10 @@
         if (bwr.write_consumed > 0) {
             if (bwr.write_consumed < mOut.dataSize())
                 mOut.remove(0, bwr.write_consumed);
-            else
+            else {
                 mOut.setDataSize(0);
+                processPostWriteDerefs();
+            }
         }
         if (bwr.read_consumed > 0) {
             mIn.setDataSize(bwr.read_consumed);
diff --git a/Static.cpp b/Static.cpp
index cdd3c7d..87f632c 100644
--- a/Static.cpp
+++ b/Static.cpp
@@ -73,7 +73,7 @@
 
 // ------------ ProcessState.cpp
 
-Mutex gProcessMutex;
+Mutex& gProcessMutex = *new Mutex;
 sp<ProcessState> gProcess;
 
 }   // namespace hardware
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index f53cdd9..28ae470 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -67,9 +67,9 @@
                                          uint32_t code, const Parcel& data,
                                          Parcel* reply, uint32_t flags);
 
-            void                incStrongHandle(int32_t handle);
+            void                incStrongHandle(int32_t handle, BpHwBinder *proxy);
             void                decStrongHandle(int32_t handle);
-            void                incWeakHandle(int32_t handle);
+            void                incWeakHandle(int32_t handle, BpHwBinder *proxy);
             void                decWeakHandle(int32_t handle);
             status_t            attemptIncStrongHandle(int32_t handle);
     static  void                expungeHandle(int32_t handle, IBinder* binder);
@@ -116,6 +116,7 @@
             status_t            getAndExecuteCommand();
             status_t            executeCommand(int32_t command);
             void                processPendingDerefs();
+            void                processPostWriteDerefs();
 
             void                clearCaller();
 
@@ -129,7 +130,8 @@
     const   pid_t               mMyThreadId;
             Vector<BHwBinder*>    mPendingStrongDerefs;
             Vector<RefBase::weakref_type*> mPendingWeakDerefs;
-
+            Vector<RefBase*>    mPostWriteStrongDerefs;
+            Vector<RefBase::weakref_type*> mPostWriteWeakDerefs;
             Parcel              mIn;
             Parcel              mOut;
             status_t            mLastError;
diff --git a/include/hwbinder/Static.h b/include/hwbinder/Static.h
index 99821ca..4b84c89 100644
--- a/include/hwbinder/Static.h
+++ b/include/hwbinder/Static.h
@@ -29,7 +29,7 @@
 extern Vector<int32_t> gTextBuffers;
 
 // For ProcessState.cpp
-extern Mutex gProcessMutex;
+extern Mutex& gProcessMutex;
 extern sp<ProcessState> gProcess;
 
 }   // namespace hardware