Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d552fb8 authored by Chong Zhang's avatar Chong Zhang
Browse files

stagefright: unblock stop if already in error state

If we received an error from component during stopping, or we
already have a sticky error when we received a stop request,
post reply with error immediatly to unblock the client.

Internally, we process the stop as usual and stay in STOPPING
state. If the client doesn't do anything after that, we wait
for the component's shutdown complete. (It's possible it never
completes, and we leak the resouce; but that's still better than
leaking the resource AND have the app ANR.) If the app initiates
release or reset, we'll release with timeout.

bug: 31671152
Change-Id: I8b7ada773c1fff77aff736efd40087bd3e9b178e
parent 116974f0
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -1098,14 +1098,16 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                            break;
                        }

                        case STOPPING:
                        case RELEASING:
                        {
                            // Ignore the error, assuming we'll still get
                            // the shutdown complete notification.

                            // the shutdown complete notification. If we
                            // don't, we'll timeout and force release.
                            sendErrorResponse = false;

                        }
                        // fall-thru
                        case STOPPING:
                        {
                            if (mFlags & kFlagSawMediaServerDie) {
                                // MediaServer died, there definitely won't
                                // be a shutdown complete notification after
@@ -1119,6 +1121,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                    mComponentName.clear();
                                }
                                (new AMessage)->postReply(mReplyID);
                                sendErrorResponse = false;
                            }
                            break;
                        }
@@ -1576,6 +1579,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

                case CodecBase::kWhatShutdownCompleted:
                {
                    if (mState == UNINITIALIZED) {
                        // Ignore shutdown complete if we're already released.
                        break;
                    }
                    if (mState == STOPPING) {
                        setState(INITIALIZED);
                    } else {
@@ -1897,7 +1904,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                }
            }

            if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
            bool isReleasingAllocatedComponent =
                    (mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED;
            if (!isReleasingAllocatedComponent // See 1
                    && mState != INITIALIZED
                    && mState != CONFIGURED && !isExecuting()) {
                // 1) Permit release to shut down the component if allocated.
@@ -1921,6 +1930,14 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                break;
            }

            // If we're flushing, or we're stopping but received a release
            // request, post the reply for the pending call first, and consider
            // it done. The reply token will be replaced after this, and we'll
            // no longer be able to reply.
            if (mState == FLUSHING || mState == STOPPING) {
                (new AMessage)->postReply(mReplyID);
            }

            if (mFlags & kFlagSawMediaServerDie) {
                // It's dead, Jim. Don't expect initiateShutdown to yield
                // any useful results now...
@@ -1932,6 +1949,15 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                break;
            }

            // If we already have an error, component may not be able to
            // complete the shutdown properly. If we're stopping, post the
            // reply now with an error to unblock the client, client can
            // release after the failure (instead of ANR).
            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
                PostReplyWithError(replyID, getStickyError());
                break;
            }

            mReplyID = replyID;
            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);

@@ -1943,6 +1969,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
                pushBlankBuffersToNativeWindow(mSurface.get());
            }

            break;
        }