Loading libs/binder/Binder.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,22 @@ status_t IBinder::getExtension(sp<IBinder>* out) { return reply.readNullableStrongBinder(out); } status_t IBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { BpBinder* proxy = this->remoteBinder(); if (proxy != nullptr) { return proxy->addFrozenStateChangeCallback(callback); } return INVALID_OPERATION; } status_t IBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { BpBinder* proxy = this->remoteBinder(); if (proxy != nullptr) { return proxy->removeFrozenStateChangeCallback(callback); } return INVALID_OPERATION; } status_t IBinder::getDebugPid(pid_t* out) { BBinder* local = this->localBinder(); if (local != nullptr) { Loading libs/binder/BpBinder.cpp +121 −0 Original line number Diff line number Diff line Loading @@ -566,6 +566,123 @@ void BpBinder::sendObituary() } } status_t BpBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "addFrozenStateChangeCallback() is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); LOG_ALWAYS_FATAL_IF(ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0, "addFrozenStateChangeCallback on %s but there are no threads " "(yet?) listening to incoming transactions. See " "ProcessState::startThreadPool " "and ProcessState::setThreadPoolMaxThreadCount. Generally you should " "setup the binder threadpool before other initialization steps.", String8(getInterfaceDescriptor()).c_str()); LOG_ALWAYS_FATAL_IF(callback == nullptr, "addFrozenStateChangeCallback(): callback must be non-NULL"); const sp<FrozenStateChangeCallback> strongCallback = callback.promote(); if (strongCallback == nullptr) { return BAD_VALUE; } { RpcMutexUniqueLock _l(mLock); if (!mFrozen) { ALOGV("Requesting freeze notification: %p handle %d\n", this, binderHandle()); IPCThreadState* self = IPCThreadState::self(); status_t status = self->addFrozenStateChangeCallback(binderHandle(), this); if (status != NO_ERROR) { // Avoids logspam if kernel does not support freeze // notification. if (status != INVALID_OPERATION) { ALOGE("IPCThreadState.addFrozenStateChangeCallback " "failed with %s. %p handle %d\n", statusToString(status).c_str(), this, binderHandle()); } return status; } mFrozen = std::make_unique<FrozenStateChange>(); if (!mFrozen) { std::ignore = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); return NO_MEMORY; } } if (mFrozen->initialStateReceived) { strongCallback->onStateChanged(wp<BpBinder>::fromExisting(this), mFrozen->isFrozen ? FrozenStateChangeCallback::State::FROZEN : FrozenStateChangeCallback::State::UNFROZEN); } ssize_t res = mFrozen->callbacks.add(callback); if (res < 0) { return res; } return NO_ERROR; } } status_t BpBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "removeFrozenStateChangeCallback() is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); RpcMutexUniqueLock _l(mLock); const size_t N = mFrozen ? mFrozen->callbacks.size() : 0; for (size_t i = 0; i < N; i++) { if (mFrozen->callbacks.itemAt(i) == callback) { mFrozen->callbacks.removeAt(i); if (mFrozen->callbacks.size() == 0) { ALOGV("Clearing freeze notification: %p handle %d\n", this, binderHandle()); status_t status = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); if (status != NO_ERROR) { ALOGE("Unexpected error from " "IPCThreadState.removeFrozenStateChangeCallback: %s. " "%p handle %d\n", statusToString(status).c_str(), this, binderHandle()); } mFrozen.reset(); } return NO_ERROR; } } return NAME_NOT_FOUND; } void BpBinder::onFrozenStateChanged(bool isFrozen) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "onFrozenStateChanged is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); ALOGV("Sending frozen state change notification for proxy %p handle %d, isFrozen=%s\n", this, binderHandle(), isFrozen ? "true" : "false"); RpcMutexUniqueLock _l(mLock); if (!mFrozen) { return; } bool stateChanged = !mFrozen->initialStateReceived || mFrozen->isFrozen != isFrozen; if (stateChanged) { mFrozen->isFrozen = isFrozen; mFrozen->initialStateReceived = true; for (size_t i = 0; i < mFrozen->callbacks.size();) { sp<FrozenStateChangeCallback> callback = mFrozen->callbacks.itemAt(i).promote(); if (callback != nullptr) { callback->onStateChanged(wp<BpBinder>::fromExisting(this), isFrozen ? FrozenStateChangeCallback::State::FROZEN : FrozenStateChangeCallback::State::UNFROZEN); i++; } else { mFrozen->callbacks.removeItemsAt(i); } } } } void BpBinder::reportOneDeath(const Obituary& obit) { sp<DeathRecipient> recipient = obit.recipient.promote(); Loading Loading @@ -695,6 +812,10 @@ void BpBinder::onLastStrongRef(const void* /*id*/) { if (ipc) ipc->clearDeathNotification(binderHandle(), this); mObituaries = nullptr; } if (mFrozen != nullptr) { std::ignore = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); mFrozen.reset(); } mLock.unlock(); if (obits != nullptr) { Loading libs/binder/IPCThreadState.cpp +96 −18 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ static const char* kReturnStrings[] = { "BR_FROZEN_REPLY", "BR_ONEWAY_SPAM_SUSPECT", "BR_TRANSACTION_PENDING_FROZEN", "BR_FROZEN_BINDER", "BR_CLEAR_FREEZE_NOTIFICATION_DONE", }; static const char* kCommandStrings[] = { Loading @@ -108,7 +110,12 @@ static const char *kCommandStrings[] = { "BC_EXIT_LOOPER", "BC_REQUEST_DEATH_NOTIFICATION", "BC_CLEAR_DEATH_NOTIFICATION", "BC_DEAD_BINDER_DONE" "BC_DEAD_BINDER_DONE", "BC_TRANSACTION_SG", "BC_REPLY_SG", "BC_REQUEST_FREEZE_NOTIFICATION", "BC_CLEAR_FREEZE_NOTIFICATION", "BC_FREEZE_NOTIFICATION_DONE", }; static const int64_t kWorkSourcePropagatedBitIndex = 32; Loading Loading @@ -203,6 +210,18 @@ static const void* printReturnCommand(std::ostream& out, const void* _cmd) { out << ": death cookie " << (void*)(uint64_t)c; } break; case BR_FROZEN_BINDER: { const int32_t c = *cmd++; const int32_t h = *cmd++; const int32_t isFrozen = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c << " isFrozen: " << isFrozen; } break; case BR_CLEAR_FREEZE_NOTIFICATION_DONE: { const int32_t c = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c; } break; default: // no details to show for: BR_OK, BR_DEAD_REPLY, // BR_TRANSACTION_COMPLETE, BR_FINISHED Loading Loading @@ -270,11 +289,23 @@ static const void* printCommand(std::ostream& out, const void* _cmd) { out << ": handle=" << h << " (death cookie " << (void*)(uint64_t)c << ")"; } break; case BC_REQUEST_FREEZE_NOTIFICATION: case BC_CLEAR_FREEZE_NOTIFICATION: { const int32_t h = *cmd++; const int32_t c = *cmd++; out << ": handle=" << h << " (freeze cookie " << (void*)(uint64_t)c << ")"; } break; case BC_DEAD_BINDER_DONE: { const int32_t c = *cmd++; out << ": death cookie " << (void*)(uint64_t)c; } break; case BC_FREEZE_NOTIFICATION_DONE: { const int32_t c = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c; } break; default: // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER, // BC_EXIT_LOOPER Loading Loading @@ -953,6 +984,33 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) return NO_ERROR; } status_t IPCThreadState::addFrozenStateChangeCallback(int32_t handle, BpBinder* proxy) { static bool isSupported = ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); if (!isSupported) { return INVALID_OPERATION; } proxy->getWeakRefs()->incWeak(proxy); mOut.writeInt32(BC_REQUEST_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); return NO_ERROR; } status_t IPCThreadState::removeFrozenStateChangeCallback(int32_t handle, BpBinder* proxy) { static bool isSupported = ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); if (!isSupported) { return INVALID_OPERATION; } mOut.writeInt32(BC_CLEAR_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); return NO_ERROR; } IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mServingStackPointer(nullptr), Loading Loading @@ -1487,6 +1545,26 @@ status_t IPCThreadState::executeCommand(int32_t cmd) proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FROZEN_BINDER: { const struct binder_frozen_state_info* data = reinterpret_cast<const struct binder_frozen_state_info*>( mIn.readInplace(sizeof(struct binder_frozen_state_info))); if (data == nullptr) { result = UNKNOWN_ERROR; break; } BpBinder* proxy = (BpBinder*)data->cookie; bool isFrozen = mIn.readInt32() > 0; proxy->getPrivateAccessor().onFrozenStateChanged(data->is_frozen); mOut.writeInt32(BC_FREEZE_NOTIFICATION_DONE); mOut.writePointer(data->cookie); } break; case BR_CLEAR_FREEZE_NOTIFICATION_DONE: { BpBinder* proxy = (BpBinder*)mIn.readPointer(); proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FINISHED: result = TIMED_OUT; break; Loading libs/binder/ProcessState.cpp +31 −19 Original line number Diff line number Diff line Loading @@ -56,6 +56,25 @@ const char* kDefaultDriver = "/dev/binder"; // ------------------------------------------------------------------------- namespace { bool readDriverFeatureFile(const char* filename) { int fd = open(filename, O_RDONLY | O_CLOEXEC); char on; if (fd == -1) { ALOGE_IF(errno != ENOENT, "%s: cannot open %s: %s", __func__, filename, strerror(errno)); return false; } if (read(fd, &on, sizeof(on)) == -1) { ALOGE("%s: error reading to %s: %s", __func__, filename, strerror(errno)); close(fd); return false; } close(fd); return on == '1'; } } // namespace namespace android { using namespace android::binder::impl; Loading Loading @@ -484,27 +503,20 @@ bool ProcessState::isThreadPoolStarted() const { #define DRIVER_FEATURES_PATH "/dev/binderfs/features/" bool ProcessState::isDriverFeatureEnabled(const DriverFeature feature) { static const char* const names[] = { [static_cast<int>(DriverFeature::ONEWAY_SPAM_DETECTION)] = DRIVER_FEATURES_PATH "oneway_spam_detection", [static_cast<int>(DriverFeature::EXTENDED_ERROR)] = DRIVER_FEATURES_PATH "extended_error", }; int fd = open(names[static_cast<int>(feature)], O_RDONLY | O_CLOEXEC); char on; if (fd == -1) { ALOGE_IF(errno != ENOENT, "%s: cannot open %s: %s", __func__, names[static_cast<int>(feature)], strerror(errno)); return false; // Use static variable to cache the results. if (feature == DriverFeature::ONEWAY_SPAM_DETECTION) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "oneway_spam_detection"); return enabled; } if (read(fd, &on, sizeof(on)) == -1) { ALOGE("%s: error reading to %s: %s", __func__, names[static_cast<int>(feature)], strerror(errno)); close(fd); return false; if (feature == DriverFeature::EXTENDED_ERROR) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "extended_error"); return enabled; } close(fd); return on == '1'; if (feature == DriverFeature::FREEZE_NOTIFICATION) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "freeze_notification"); return enabled; } return false; } status_t ProcessState::enableOnewaySpamDetection(bool enable) { Loading libs/binder/binder_module.h +30 −0 Original line number Diff line number Diff line Loading @@ -32,4 +32,34 @@ #include <linux/android/binder.h> #include <sys/ioctl.h> struct binder_frozen_state_info { binder_uintptr_t cookie; __u32 is_frozen; }; #ifndef BR_FROZEN_BINDER // Temporary definition of BR_FROZEN_BINDER until UAPI binder.h includes it. #define BR_FROZEN_BINDER _IOR('r', 21, struct binder_frozen_state_info) #endif // BR_FROZEN_BINDER #ifndef BR_CLEAR_FREEZE_NOTIFICATION_DONE // Temporary definition of BR_CLEAR_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it. #define BR_CLEAR_FREEZE_NOTIFICATION_DONE _IOR('r', 22, binder_uintptr_t) #endif // BR_CLEAR_FREEZE_NOTIFICATION_DONE #ifndef BC_REQUEST_FREEZE_NOTIFICATION // Temporary definition of BC_REQUEST_FREEZE_NOTIFICATION until UAPI binder.h includes it. #define BC_REQUEST_FREEZE_NOTIFICATION _IOW('c', 19, struct binder_handle_cookie) #endif // BC_REQUEST_FREEZE_NOTIFICATION #ifndef BC_CLEAR_FREEZE_NOTIFICATION // Temporary definition of BC_CLEAR_FREEZE_NOTIFICATION until UAPI binder.h includes it. #define BC_CLEAR_FREEZE_NOTIFICATION _IOW('c', 20, struct binder_handle_cookie) #endif // BC_CLEAR_FREEZE_NOTIFICATION #ifndef BC_FREEZE_NOTIFICATION_DONE // Temporary definition of BC_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it. #define BC_FREEZE_NOTIFICATION_DONE _IOW('c', 21, binder_uintptr_t) #endif // BC_FREEZE_NOTIFICATION_DONE #endif // _BINDER_MODULE_H_ Loading
libs/binder/Binder.cpp +16 −0 Original line number Diff line number Diff line Loading @@ -143,6 +143,22 @@ status_t IBinder::getExtension(sp<IBinder>* out) { return reply.readNullableStrongBinder(out); } status_t IBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { BpBinder* proxy = this->remoteBinder(); if (proxy != nullptr) { return proxy->addFrozenStateChangeCallback(callback); } return INVALID_OPERATION; } status_t IBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { BpBinder* proxy = this->remoteBinder(); if (proxy != nullptr) { return proxy->removeFrozenStateChangeCallback(callback); } return INVALID_OPERATION; } status_t IBinder::getDebugPid(pid_t* out) { BBinder* local = this->localBinder(); if (local != nullptr) { Loading
libs/binder/BpBinder.cpp +121 −0 Original line number Diff line number Diff line Loading @@ -566,6 +566,123 @@ void BpBinder::sendObituary() } } status_t BpBinder::addFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "addFrozenStateChangeCallback() is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); LOG_ALWAYS_FATAL_IF(ProcessState::self()->getThreadPoolMaxTotalThreadCount() == 0, "addFrozenStateChangeCallback on %s but there are no threads " "(yet?) listening to incoming transactions. See " "ProcessState::startThreadPool " "and ProcessState::setThreadPoolMaxThreadCount. Generally you should " "setup the binder threadpool before other initialization steps.", String8(getInterfaceDescriptor()).c_str()); LOG_ALWAYS_FATAL_IF(callback == nullptr, "addFrozenStateChangeCallback(): callback must be non-NULL"); const sp<FrozenStateChangeCallback> strongCallback = callback.promote(); if (strongCallback == nullptr) { return BAD_VALUE; } { RpcMutexUniqueLock _l(mLock); if (!mFrozen) { ALOGV("Requesting freeze notification: %p handle %d\n", this, binderHandle()); IPCThreadState* self = IPCThreadState::self(); status_t status = self->addFrozenStateChangeCallback(binderHandle(), this); if (status != NO_ERROR) { // Avoids logspam if kernel does not support freeze // notification. if (status != INVALID_OPERATION) { ALOGE("IPCThreadState.addFrozenStateChangeCallback " "failed with %s. %p handle %d\n", statusToString(status).c_str(), this, binderHandle()); } return status; } mFrozen = std::make_unique<FrozenStateChange>(); if (!mFrozen) { std::ignore = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); return NO_MEMORY; } } if (mFrozen->initialStateReceived) { strongCallback->onStateChanged(wp<BpBinder>::fromExisting(this), mFrozen->isFrozen ? FrozenStateChangeCallback::State::FROZEN : FrozenStateChangeCallback::State::UNFROZEN); } ssize_t res = mFrozen->callbacks.add(callback); if (res < 0) { return res; } return NO_ERROR; } } status_t BpBinder::removeFrozenStateChangeCallback(const wp<FrozenStateChangeCallback>& callback) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "removeFrozenStateChangeCallback() is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); RpcMutexUniqueLock _l(mLock); const size_t N = mFrozen ? mFrozen->callbacks.size() : 0; for (size_t i = 0; i < N; i++) { if (mFrozen->callbacks.itemAt(i) == callback) { mFrozen->callbacks.removeAt(i); if (mFrozen->callbacks.size() == 0) { ALOGV("Clearing freeze notification: %p handle %d\n", this, binderHandle()); status_t status = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); if (status != NO_ERROR) { ALOGE("Unexpected error from " "IPCThreadState.removeFrozenStateChangeCallback: %s. " "%p handle %d\n", statusToString(status).c_str(), this, binderHandle()); } mFrozen.reset(); } return NO_ERROR; } } return NAME_NOT_FOUND; } void BpBinder::onFrozenStateChanged(bool isFrozen) { LOG_ALWAYS_FATAL_IF(isRpcBinder(), "onFrozenStateChanged is not supported for RPC Binder."); LOG_ALWAYS_FATAL_IF(!kEnableKernelIpc, "Binder kernel driver disabled at build time"); ALOGV("Sending frozen state change notification for proxy %p handle %d, isFrozen=%s\n", this, binderHandle(), isFrozen ? "true" : "false"); RpcMutexUniqueLock _l(mLock); if (!mFrozen) { return; } bool stateChanged = !mFrozen->initialStateReceived || mFrozen->isFrozen != isFrozen; if (stateChanged) { mFrozen->isFrozen = isFrozen; mFrozen->initialStateReceived = true; for (size_t i = 0; i < mFrozen->callbacks.size();) { sp<FrozenStateChangeCallback> callback = mFrozen->callbacks.itemAt(i).promote(); if (callback != nullptr) { callback->onStateChanged(wp<BpBinder>::fromExisting(this), isFrozen ? FrozenStateChangeCallback::State::FROZEN : FrozenStateChangeCallback::State::UNFROZEN); i++; } else { mFrozen->callbacks.removeItemsAt(i); } } } } void BpBinder::reportOneDeath(const Obituary& obit) { sp<DeathRecipient> recipient = obit.recipient.promote(); Loading Loading @@ -695,6 +812,10 @@ void BpBinder::onLastStrongRef(const void* /*id*/) { if (ipc) ipc->clearDeathNotification(binderHandle(), this); mObituaries = nullptr; } if (mFrozen != nullptr) { std::ignore = IPCThreadState::self()->removeFrozenStateChangeCallback(binderHandle(), this); mFrozen.reset(); } mLock.unlock(); if (obits != nullptr) { Loading
libs/binder/IPCThreadState.cpp +96 −18 Original line number Diff line number Diff line Loading @@ -89,6 +89,8 @@ static const char* kReturnStrings[] = { "BR_FROZEN_REPLY", "BR_ONEWAY_SPAM_SUSPECT", "BR_TRANSACTION_PENDING_FROZEN", "BR_FROZEN_BINDER", "BR_CLEAR_FREEZE_NOTIFICATION_DONE", }; static const char* kCommandStrings[] = { Loading @@ -108,7 +110,12 @@ static const char *kCommandStrings[] = { "BC_EXIT_LOOPER", "BC_REQUEST_DEATH_NOTIFICATION", "BC_CLEAR_DEATH_NOTIFICATION", "BC_DEAD_BINDER_DONE" "BC_DEAD_BINDER_DONE", "BC_TRANSACTION_SG", "BC_REPLY_SG", "BC_REQUEST_FREEZE_NOTIFICATION", "BC_CLEAR_FREEZE_NOTIFICATION", "BC_FREEZE_NOTIFICATION_DONE", }; static const int64_t kWorkSourcePropagatedBitIndex = 32; Loading Loading @@ -203,6 +210,18 @@ static const void* printReturnCommand(std::ostream& out, const void* _cmd) { out << ": death cookie " << (void*)(uint64_t)c; } break; case BR_FROZEN_BINDER: { const int32_t c = *cmd++; const int32_t h = *cmd++; const int32_t isFrozen = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c << " isFrozen: " << isFrozen; } break; case BR_CLEAR_FREEZE_NOTIFICATION_DONE: { const int32_t c = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c; } break; default: // no details to show for: BR_OK, BR_DEAD_REPLY, // BR_TRANSACTION_COMPLETE, BR_FINISHED Loading Loading @@ -270,11 +289,23 @@ static const void* printCommand(std::ostream& out, const void* _cmd) { out << ": handle=" << h << " (death cookie " << (void*)(uint64_t)c << ")"; } break; case BC_REQUEST_FREEZE_NOTIFICATION: case BC_CLEAR_FREEZE_NOTIFICATION: { const int32_t h = *cmd++; const int32_t c = *cmd++; out << ": handle=" << h << " (freeze cookie " << (void*)(uint64_t)c << ")"; } break; case BC_DEAD_BINDER_DONE: { const int32_t c = *cmd++; out << ": death cookie " << (void*)(uint64_t)c; } break; case BC_FREEZE_NOTIFICATION_DONE: { const int32_t c = *cmd++; out << ": freeze cookie " << (void*)(uint64_t)c; } break; default: // no details to show for: BC_REGISTER_LOOPER, BC_ENTER_LOOPER, // BC_EXIT_LOOPER Loading Loading @@ -953,6 +984,33 @@ status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) return NO_ERROR; } status_t IPCThreadState::addFrozenStateChangeCallback(int32_t handle, BpBinder* proxy) { static bool isSupported = ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); if (!isSupported) { return INVALID_OPERATION; } proxy->getWeakRefs()->incWeak(proxy); mOut.writeInt32(BC_REQUEST_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); return NO_ERROR; } status_t IPCThreadState::removeFrozenStateChangeCallback(int32_t handle, BpBinder* proxy) { static bool isSupported = ProcessState::isDriverFeatureEnabled(ProcessState::DriverFeature::FREEZE_NOTIFICATION); if (!isSupported) { return INVALID_OPERATION; } mOut.writeInt32(BC_CLEAR_FREEZE_NOTIFICATION); mOut.writeInt32((int32_t)handle); mOut.writePointer((uintptr_t)proxy); flushCommands(); return NO_ERROR; } IPCThreadState::IPCThreadState() : mProcess(ProcessState::self()), mServingStackPointer(nullptr), Loading Loading @@ -1487,6 +1545,26 @@ status_t IPCThreadState::executeCommand(int32_t cmd) proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FROZEN_BINDER: { const struct binder_frozen_state_info* data = reinterpret_cast<const struct binder_frozen_state_info*>( mIn.readInplace(sizeof(struct binder_frozen_state_info))); if (data == nullptr) { result = UNKNOWN_ERROR; break; } BpBinder* proxy = (BpBinder*)data->cookie; bool isFrozen = mIn.readInt32() > 0; proxy->getPrivateAccessor().onFrozenStateChanged(data->is_frozen); mOut.writeInt32(BC_FREEZE_NOTIFICATION_DONE); mOut.writePointer(data->cookie); } break; case BR_CLEAR_FREEZE_NOTIFICATION_DONE: { BpBinder* proxy = (BpBinder*)mIn.readPointer(); proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FINISHED: result = TIMED_OUT; break; Loading
libs/binder/ProcessState.cpp +31 −19 Original line number Diff line number Diff line Loading @@ -56,6 +56,25 @@ const char* kDefaultDriver = "/dev/binder"; // ------------------------------------------------------------------------- namespace { bool readDriverFeatureFile(const char* filename) { int fd = open(filename, O_RDONLY | O_CLOEXEC); char on; if (fd == -1) { ALOGE_IF(errno != ENOENT, "%s: cannot open %s: %s", __func__, filename, strerror(errno)); return false; } if (read(fd, &on, sizeof(on)) == -1) { ALOGE("%s: error reading to %s: %s", __func__, filename, strerror(errno)); close(fd); return false; } close(fd); return on == '1'; } } // namespace namespace android { using namespace android::binder::impl; Loading Loading @@ -484,27 +503,20 @@ bool ProcessState::isThreadPoolStarted() const { #define DRIVER_FEATURES_PATH "/dev/binderfs/features/" bool ProcessState::isDriverFeatureEnabled(const DriverFeature feature) { static const char* const names[] = { [static_cast<int>(DriverFeature::ONEWAY_SPAM_DETECTION)] = DRIVER_FEATURES_PATH "oneway_spam_detection", [static_cast<int>(DriverFeature::EXTENDED_ERROR)] = DRIVER_FEATURES_PATH "extended_error", }; int fd = open(names[static_cast<int>(feature)], O_RDONLY | O_CLOEXEC); char on; if (fd == -1) { ALOGE_IF(errno != ENOENT, "%s: cannot open %s: %s", __func__, names[static_cast<int>(feature)], strerror(errno)); return false; // Use static variable to cache the results. if (feature == DriverFeature::ONEWAY_SPAM_DETECTION) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "oneway_spam_detection"); return enabled; } if (read(fd, &on, sizeof(on)) == -1) { ALOGE("%s: error reading to %s: %s", __func__, names[static_cast<int>(feature)], strerror(errno)); close(fd); return false; if (feature == DriverFeature::EXTENDED_ERROR) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "extended_error"); return enabled; } close(fd); return on == '1'; if (feature == DriverFeature::FREEZE_NOTIFICATION) { static bool enabled = readDriverFeatureFile(DRIVER_FEATURES_PATH "freeze_notification"); return enabled; } return false; } status_t ProcessState::enableOnewaySpamDetection(bool enable) { Loading
libs/binder/binder_module.h +30 −0 Original line number Diff line number Diff line Loading @@ -32,4 +32,34 @@ #include <linux/android/binder.h> #include <sys/ioctl.h> struct binder_frozen_state_info { binder_uintptr_t cookie; __u32 is_frozen; }; #ifndef BR_FROZEN_BINDER // Temporary definition of BR_FROZEN_BINDER until UAPI binder.h includes it. #define BR_FROZEN_BINDER _IOR('r', 21, struct binder_frozen_state_info) #endif // BR_FROZEN_BINDER #ifndef BR_CLEAR_FREEZE_NOTIFICATION_DONE // Temporary definition of BR_CLEAR_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it. #define BR_CLEAR_FREEZE_NOTIFICATION_DONE _IOR('r', 22, binder_uintptr_t) #endif // BR_CLEAR_FREEZE_NOTIFICATION_DONE #ifndef BC_REQUEST_FREEZE_NOTIFICATION // Temporary definition of BC_REQUEST_FREEZE_NOTIFICATION until UAPI binder.h includes it. #define BC_REQUEST_FREEZE_NOTIFICATION _IOW('c', 19, struct binder_handle_cookie) #endif // BC_REQUEST_FREEZE_NOTIFICATION #ifndef BC_CLEAR_FREEZE_NOTIFICATION // Temporary definition of BC_CLEAR_FREEZE_NOTIFICATION until UAPI binder.h includes it. #define BC_CLEAR_FREEZE_NOTIFICATION _IOW('c', 20, struct binder_handle_cookie) #endif // BC_CLEAR_FREEZE_NOTIFICATION #ifndef BC_FREEZE_NOTIFICATION_DONE // Temporary definition of BC_FREEZE_NOTIFICATION_DONE until UAPI binder.h includes it. #define BC_FREEZE_NOTIFICATION_DONE _IOW('c', 21, binder_uintptr_t) #endif // BC_FREEZE_NOTIFICATION_DONE #endif // _BINDER_MODULE_H_