@@ -566,6 +566,123 @@ void BpBinder::sendObituary()
566566 }
567567}
568568
569+ status_t BpBinder::addFrozenStateChangeCallback (const wp<FrozenStateChangeCallback>& callback) {
570+ LOG_ALWAYS_FATAL_IF (isRpcBinder (),
571+ " addFrozenStateChangeCallback() is not supported for RPC Binder." );
572+ LOG_ALWAYS_FATAL_IF (!kEnableKernelIpc , " Binder kernel driver disabled at build time" );
573+ LOG_ALWAYS_FATAL_IF (ProcessState::self ()->getThreadPoolMaxTotalThreadCount () == 0 ,
574+ " addFrozenStateChangeCallback on %s but there are no threads "
575+ " (yet?) listening to incoming transactions. See "
576+ " ProcessState::startThreadPool "
577+ " and ProcessState::setThreadPoolMaxThreadCount. Generally you should "
578+ " setup the binder threadpool before other initialization steps." ,
579+ String8 (getInterfaceDescriptor ()).c_str ());
580+ LOG_ALWAYS_FATAL_IF (callback == nullptr ,
581+ " addFrozenStateChangeCallback(): callback must be non-NULL" );
582+
583+ const sp<FrozenStateChangeCallback> strongCallback = callback.promote ();
584+ if (strongCallback == nullptr ) {
585+ return BAD_VALUE;
586+ }
587+
588+ {
589+ RpcMutexUniqueLock _l (mLock );
590+ if (!mFrozen ) {
591+ ALOGV (" Requesting freeze notification: %p handle %d\n " , this , binderHandle ());
592+ IPCThreadState* self = IPCThreadState::self ();
593+ status_t status = self->addFrozenStateChangeCallback (binderHandle (), this );
594+ if (status != NO_ERROR) {
595+ // Avoids logspam if kernel does not support freeze
596+ // notification.
597+ if (status != INVALID_OPERATION) {
598+ ALOGE (" IPCThreadState.addFrozenStateChangeCallback "
599+ " failed with %s. %p handle %d\n " ,
600+ statusToString (status).c_str (), this , binderHandle ());
601+ }
602+ return status;
603+ }
604+ mFrozen = std::make_unique<FrozenStateChange>();
605+ if (!mFrozen ) {
606+ std::ignore =
607+ IPCThreadState::self ()->removeFrozenStateChangeCallback (binderHandle (),
608+ this );
609+ return NO_MEMORY;
610+ }
611+ }
612+ if (mFrozen ->initialStateReceived ) {
613+ strongCallback->onStateChanged (wp<BpBinder>::fromExisting (this ),
614+ mFrozen ->isFrozen
615+ ? FrozenStateChangeCallback::State::FROZEN
616+ : FrozenStateChangeCallback::State::UNFROZEN);
617+ }
618+ ssize_t res = mFrozen ->callbacks .add (callback);
619+ if (res < 0 ) {
620+ return res;
621+ }
622+ return NO_ERROR;
623+ }
624+ }
625+
626+ status_t BpBinder::removeFrozenStateChangeCallback (const wp<FrozenStateChangeCallback>& callback) {
627+ LOG_ALWAYS_FATAL_IF (isRpcBinder (),
628+ " removeFrozenStateChangeCallback() is not supported for RPC Binder." );
629+ LOG_ALWAYS_FATAL_IF (!kEnableKernelIpc , " Binder kernel driver disabled at build time" );
630+
631+ RpcMutexUniqueLock _l (mLock );
632+
633+ const size_t N = mFrozen ? mFrozen ->callbacks .size () : 0 ;
634+ for (size_t i = 0 ; i < N; i++) {
635+ if (mFrozen ->callbacks .itemAt (i) == callback) {
636+ mFrozen ->callbacks .removeAt (i);
637+ if (mFrozen ->callbacks .size () == 0 ) {
638+ ALOGV (" Clearing freeze notification: %p handle %d\n " , this , binderHandle ());
639+ status_t status =
640+ IPCThreadState::self ()->removeFrozenStateChangeCallback (binderHandle (),
641+ this );
642+ if (status != NO_ERROR) {
643+ ALOGE (" Unexpected error from "
644+ " IPCThreadState.removeFrozenStateChangeCallback: %s. "
645+ " %p handle %d\n " ,
646+ statusToString (status).c_str (), this , binderHandle ());
647+ }
648+ mFrozen .reset ();
649+ }
650+ return NO_ERROR;
651+ }
652+ }
653+
654+ return NAME_NOT_FOUND;
655+ }
656+
657+ void BpBinder::onFrozenStateChanged (bool isFrozen) {
658+ LOG_ALWAYS_FATAL_IF (isRpcBinder (), " onFrozenStateChanged is not supported for RPC Binder." );
659+ LOG_ALWAYS_FATAL_IF (!kEnableKernelIpc , " Binder kernel driver disabled at build time" );
660+
661+ ALOGV (" Sending frozen state change notification for proxy %p handle %d, isFrozen=%s\n " , this ,
662+ binderHandle (), isFrozen ? " true" : " false" );
663+
664+ RpcMutexUniqueLock _l (mLock );
665+ if (!mFrozen ) {
666+ return ;
667+ }
668+ bool stateChanged = !mFrozen ->initialStateReceived || mFrozen ->isFrozen != isFrozen;
669+ if (stateChanged) {
670+ mFrozen ->isFrozen = isFrozen;
671+ mFrozen ->initialStateReceived = true ;
672+ for (size_t i = 0 ; i < mFrozen ->callbacks .size ();) {
673+ sp<FrozenStateChangeCallback> callback = mFrozen ->callbacks .itemAt (i).promote ();
674+ if (callback != nullptr ) {
675+ callback->onStateChanged (wp<BpBinder>::fromExisting (this ),
676+ isFrozen ? FrozenStateChangeCallback::State::FROZEN
677+ : FrozenStateChangeCallback::State::UNFROZEN);
678+ i++;
679+ } else {
680+ mFrozen ->callbacks .removeItemsAt (i);
681+ }
682+ }
683+ }
684+ }
685+
569686void BpBinder::reportOneDeath (const Obituary& obit)
570687{
571688 sp<DeathRecipient> recipient = obit.recipient .promote ();
@@ -695,6 +812,10 @@ void BpBinder::onLastStrongRef(const void* /*id*/) {
695812 if (ipc) ipc->clearDeathNotification (binderHandle (), this );
696813 mObituaries = nullptr ;
697814 }
815+ if (mFrozen != nullptr ) {
816+ std::ignore = IPCThreadState::self ()->removeFrozenStateChangeCallback (binderHandle (), this );
817+ mFrozen .reset ();
818+ }
698819 mLock .unlock ();
699820
700821 if (obits != nullptr ) {
0 commit comments