Loading libs/binder/IPCThreadState.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -860,6 +860,10 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) err = FAILED_TRANSACTION; goto finish; case BR_FROZEN_REPLY: err = FAILED_TRANSACTION; goto finish; case BR_ACQUIRE_RESULT: { ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); Loading Loading @@ -1316,6 +1320,26 @@ void IPCThreadState::threadDestructor(void *st) } } status_t IPCThreadState::freeze(pid_t pid, bool enable, uint32_t timeout_ms) { struct binder_freeze_info info; int ret = 0; info.pid = pid; info.enable = enable; info.timeout_ms = timeout_ms; #if defined(__ANDROID__) if (ioctl(self()->mProcess->mDriverFD, BINDER_FREEZE, &info) < 0) ret = -errno; #endif // // ret==-EAGAIN indicates that transactions have not drained. // Call again to poll for completion. // return ret; } void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t /*dataSize*/, Loading libs/binder/include/binder/IPCThreadState.h +15 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,20 @@ public: static IPCThreadState* self(); static IPCThreadState* selfOrNull(); // self(), but won't instantiate // Freeze or unfreeze the binder interface to a specific process. When freezing, this method // will block up to timeout_ms to process pending transactions directed to pid. Unfreeze // is immediate. Transactions to processes frozen via this method won't be delivered and the // driver will return BR_FROZEN_REPLY to the client sending them. After unfreeze, // transactions will be delivered normally. // // pid: id for the process for which the binder interface is to be frozen // enable: freeze (true) or unfreeze (false) // timeout_ms: maximum time this function is allowed to block the caller waiting for pending // binder transactions to be processed. // // returns: 0 in case of success, a value < 0 in case of error static status_t freeze(pid_t pid, bool enabled, uint32_t timeout_ms); sp<ProcessState> process(); status_t clearLastError(); Loading libs/binder/include/private/binder/binder_module.h +31 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,37 @@ namespace android { #include <sys/ioctl.h> #include <linux/android/binder.h> #ifndef BR_FROZEN_REPLY // Temporary definition of BR_FROZEN_REPLY. For production // this will come from UAPI binder.h #define BR_FROZEN_REPLY _IO('r', 18) #endif //BR_FROZEN_REPLY #ifndef BINDER_FREEZE /* * Temporary definitions for freeze support. For the final version * these will be defined in the UAPI binder.h file from upstream kernel. */ #define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) struct binder_freeze_info { // // Group-leader PID of process to be frozen // uint32_t pid; // // Enable(1) / Disable(0) freeze for given PID // uint32_t enable; // // Timeout to wait for transactions to drain. // 0: don't wait (ioctl will return EAGAIN if not drained) // N: number of ms to wait uint32_t timeout_ms; }; #endif //BINDER_FREEZE #ifdef __cplusplus } // namespace android #endif Loading libs/binder/tests/binderLibTest.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> #include <fstream> #include <poll.h> #include <pthread.h> #include <stdio.h> Loading Loading @@ -79,6 +80,8 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, BINDER_LIB_TEST_GET_SCHEDULING_POLICY, BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, BINDER_LIB_TEST_GETPID, BINDER_LIB_TEST_ECHO_VECTOR, BINDER_LIB_TEST_REJECT_BUF, }; Loading Loading @@ -399,6 +402,40 @@ TEST_F(BinderLibTest, NopTransaction) { EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, Freeze) { status_t ret; Parcel data, reply, replypid; std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze"); //Pass test on devices where the 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; } ret = m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid); int32_t pid = replypid.readInt32(); EXPECT_EQ(NO_ERROR, ret); 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)); EXPECT_EQ(FAILED_TRANSACTION, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply)); EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 0, 0)); EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply)); } TEST_F(BinderLibTest, SetError) { int32_t testValue[] = { 0, -123, 123 }; for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) { Loading Loading @@ -1178,6 +1215,12 @@ class BinderLibTestService : public BBinder pthread_mutex_unlock(&m_serverWaitMutex); return ret; } case BINDER_LIB_TEST_GETPID: reply->writeInt32(getpid()); return NO_ERROR; case BINDER_LIB_TEST_NOP_TRANSACTION_WAIT: usleep(5000); return NO_ERROR; case BINDER_LIB_TEST_NOP_TRANSACTION: return NO_ERROR; case BINDER_LIB_TEST_DELAYED_CALL_BACK: { Loading Loading
libs/binder/IPCThreadState.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -860,6 +860,10 @@ status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) err = FAILED_TRANSACTION; goto finish; case BR_FROZEN_REPLY: err = FAILED_TRANSACTION; goto finish; case BR_ACQUIRE_RESULT: { ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); Loading Loading @@ -1316,6 +1320,26 @@ void IPCThreadState::threadDestructor(void *st) } } status_t IPCThreadState::freeze(pid_t pid, bool enable, uint32_t timeout_ms) { struct binder_freeze_info info; int ret = 0; info.pid = pid; info.enable = enable; info.timeout_ms = timeout_ms; #if defined(__ANDROID__) if (ioctl(self()->mProcess->mDriverFD, BINDER_FREEZE, &info) < 0) ret = -errno; #endif // // ret==-EAGAIN indicates that transactions have not drained. // Call again to poll for completion. // return ret; } void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t /*dataSize*/, Loading
libs/binder/include/binder/IPCThreadState.h +15 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,20 @@ public: static IPCThreadState* self(); static IPCThreadState* selfOrNull(); // self(), but won't instantiate // Freeze or unfreeze the binder interface to a specific process. When freezing, this method // will block up to timeout_ms to process pending transactions directed to pid. Unfreeze // is immediate. Transactions to processes frozen via this method won't be delivered and the // driver will return BR_FROZEN_REPLY to the client sending them. After unfreeze, // transactions will be delivered normally. // // pid: id for the process for which the binder interface is to be frozen // enable: freeze (true) or unfreeze (false) // timeout_ms: maximum time this function is allowed to block the caller waiting for pending // binder transactions to be processed. // // returns: 0 in case of success, a value < 0 in case of error static status_t freeze(pid_t pid, bool enabled, uint32_t timeout_ms); sp<ProcessState> process(); status_t clearLastError(); Loading
libs/binder/include/private/binder/binder_module.h +31 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,37 @@ namespace android { #include <sys/ioctl.h> #include <linux/android/binder.h> #ifndef BR_FROZEN_REPLY // Temporary definition of BR_FROZEN_REPLY. For production // this will come from UAPI binder.h #define BR_FROZEN_REPLY _IO('r', 18) #endif //BR_FROZEN_REPLY #ifndef BINDER_FREEZE /* * Temporary definitions for freeze support. For the final version * these will be defined in the UAPI binder.h file from upstream kernel. */ #define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info) struct binder_freeze_info { // // Group-leader PID of process to be frozen // uint32_t pid; // // Enable(1) / Disable(0) freeze for given PID // uint32_t enable; // // Timeout to wait for transactions to drain. // 0: don't wait (ioctl will return EAGAIN if not drained) // N: number of ms to wait uint32_t timeout_ms; }; #endif //BINDER_FREEZE #ifdef __cplusplus } // namespace android #endif Loading
libs/binder/tests/binderLibTest.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> #include <fstream> #include <poll.h> #include <pthread.h> #include <stdio.h> Loading Loading @@ -79,6 +80,8 @@ enum BinderLibTestTranscationCode { BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION, BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION, BINDER_LIB_TEST_GET_SCHEDULING_POLICY, BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, BINDER_LIB_TEST_GETPID, BINDER_LIB_TEST_ECHO_VECTOR, BINDER_LIB_TEST_REJECT_BUF, }; Loading Loading @@ -399,6 +402,40 @@ TEST_F(BinderLibTest, NopTransaction) { EXPECT_EQ(NO_ERROR, ret); } TEST_F(BinderLibTest, Freeze) { status_t ret; Parcel data, reply, replypid; std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze"); //Pass test on devices where the 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; } ret = m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid); int32_t pid = replypid.readInt32(); EXPECT_EQ(NO_ERROR, ret); 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)); EXPECT_EQ(FAILED_TRANSACTION, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply)); EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 0, 0)); EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply)); } TEST_F(BinderLibTest, SetError) { int32_t testValue[] = { 0, -123, 123 }; for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) { Loading Loading @@ -1178,6 +1215,12 @@ class BinderLibTestService : public BBinder pthread_mutex_unlock(&m_serverWaitMutex); return ret; } case BINDER_LIB_TEST_GETPID: reply->writeInt32(getpid()); return NO_ERROR; case BINDER_LIB_TEST_NOP_TRANSACTION_WAIT: usleep(5000); return NO_ERROR; case BINDER_LIB_TEST_NOP_TRANSACTION: return NO_ERROR; case BINDER_LIB_TEST_DELAYED_CALL_BACK: { Loading