getProcessFreezeInfo reads more info from kernel

Improve primitive binder function to check if a process has any pending
binder transactions so that the freezer policy can choose to wait and
drain those pending transactions.

Bug: 198493121
Test: app launch/foreground/background stress test
Change-Id: Ia7ce6899ddaeb8e8453b0b8f3536d129b6b761d3
Merged-In: Ia7ce6899ddaeb8e8453b0b8f3536d129b6b761d3
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 445df9e..c415ea0 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -1398,6 +1398,25 @@
     return ret;
 }
 
+#ifndef __ANDROID_VNDK__
+status_t IPCThreadState::getProcessFreezeInfo(pid_t pid, uint32_t *sync_received,
+                                              uint32_t *async_received)
+{
+    int ret = 0;
+    binder_frozen_status_info info;
+    info.pid = pid;
+
+#if defined(__ANDROID__)
+    if (ioctl(self()->mProcess->mDriverFD, BINDER_GET_FROZEN_INFO, &info) < 0)
+        ret = -errno;
+#endif
+    *sync_received = info.sync_recv;
+    *async_received = info.async_recv;
+
+    return ret;
+}
+#endif
+
 status_t IPCThreadState::freeze(pid_t pid, bool enable, uint32_t timeout_ms) {
     struct binder_freeze_info info;
     int ret = 0;
diff --git a/libs/binder/binder_module.h b/libs/binder/binder_module.h
index 9dea3b4..793795e 100644
--- a/libs/binder/binder_module.h
+++ b/libs/binder/binder_module.h
@@ -74,6 +74,8 @@
     //
     // Indicates whether the process has received any sync calls since last
     // freeze (cleared at freeze/unfreeze)
+    // bit 0: received sync transaction after being frozen
+    // bit 1: new pending sync transaction during freezing
     //
     __u32 sync_recv;
     //
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 196a41b..b401ea9 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -53,6 +53,13 @@
     // Provide information about the state of a frozen process
     static  status_t            getProcessFreezeInfo(pid_t pid, bool *sync_received,
                                                     bool *async_received);
+
+    // TODO: Remove the above legacy duplicated function in next version
+#ifndef __ANDROID_VNDK__
+    static  status_t            getProcessFreezeInfo(pid_t pid, uint32_t *sync_received,
+                                                    uint32_t *async_received);
+#endif
+
             sp<ProcessState>    process();
             
             status_t            clearLastError();
diff --git a/libs/binder/libbinder.arm32.map b/libs/binder/libbinder.arm32.map
index f26c33d..9f10b67 100644
--- a/libs/binder/libbinder.arm32.map
+++ b/libs/binder/libbinder.arm32.map
@@ -149,6 +149,7 @@
     _ZN7android14IPCThreadState20clearCallingIdentityEv;
     _ZN7android14IPCThreadState20getAndExecuteCommandEv;
     _ZN7android14IPCThreadState20getProcessFreezeInfoEiPbS1_;
+    _ZN7android14IPCThreadState20getProcessFreezeInfoEiPjS1_;
     _ZN7android14IPCThreadState20handlePolledCommandsEv;
     _ZN7android14IPCThreadState20processPendingDerefsEv;
     _ZN7android14IPCThreadState20writeTransactionDataEijijRKNS_6ParcelEPi;
diff --git a/libs/binder/libbinder.arm64.map b/libs/binder/libbinder.arm64.map
index 6211250..1d3da4c 100644
--- a/libs/binder/libbinder.arm64.map
+++ b/libs/binder/libbinder.arm64.map
@@ -150,6 +150,7 @@
     _ZN7android14IPCThreadState20clearCallingIdentityEv;
     _ZN7android14IPCThreadState20getAndExecuteCommandEv;
     _ZN7android14IPCThreadState20getProcessFreezeInfoEiPbS1_;
+    _ZN7android14IPCThreadState20getProcessFreezeInfoEiPjS1_;
     _ZN7android14IPCThreadState20handlePolledCommandsEv;
     _ZN7android14IPCThreadState20processPendingDerefsEv;
     _ZN7android14IPCThreadState20writeTransactionDataEijijRKNS_6ParcelEPi;
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 5612d1d..64196ba 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -425,31 +425,30 @@
 
 TEST_F(BinderLibTest, Freeze) {
     Parcel data, reply, replypid;
-    std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze");
+    std::ifstream freezer_file("/sys/fs/cgroup/uid_0/cgroup.freeze");
 
-    //Pass test on devices where the freezer is not supported
+    // Pass test on devices where the cgroup v2 freezer is not supported
     if (freezer_file.fail()) {
         GTEST_SKIP();
         return;
     }
 
-    std::string freezer_enabled;
-    std::getline(freezer_file, freezer_enabled);
-
-    //Pass test on devices where the freezer is disabled
-    if (freezer_enabled != "1") {
-        GTEST_SKIP();
-        return;
-    }
-
     EXPECT_THAT(m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid), StatusEq(NO_ERROR));
     int32_t pid = replypid.readInt32();
     for (int i = 0; i < 10; i++) {
         EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, data, &reply, TF_ONE_WAY));
     }
-    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, 1, 0));
-    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, 1, 0));
-    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 1, 1000));
+
+    // Pass test on devices where BINDER_FREEZE ioctl is not supported
+    int ret = IPCThreadState::self()->freeze(pid, false, 0);
+    if (ret != 0) {
+        GTEST_SKIP();
+        return;
+    }
+
+    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, true, 0));
+    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, true, 0));
+    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, true, 1000));
     EXPECT_EQ(FAILED_TRANSACTION, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
 
     bool sync_received, async_received;
@@ -460,6 +459,14 @@
     EXPECT_EQ(sync_received, 1);
     EXPECT_EQ(async_received, 0);
 
+    uint32_t sync_received2, async_received2;
+
+    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->getProcessFreezeInfo(pid, &sync_received2,
+                &async_received2));
+
+    EXPECT_EQ(sync_received2, 1);
+    EXPECT_EQ(async_received2, 0);
+
     EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 0, 0));
     EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
 }