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

Commit 56067e71 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "MediaCodec: ensure reply does not get lost" am: cd2b79a8

Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/1428794

Change-Id: If4833d7e38a6dc7f46ce0ef471c6a50474d3dbcd
parents f36fa7cd cd2b79a8
Loading
Loading
Loading
Loading
+157 −47
Original line number Diff line number Diff line
@@ -1008,6 +1008,12 @@ status_t MediaCodec::PostAndAwaitResponse(
    return err;
}

void MediaCodec::PostReplyWithError(const sp<AMessage> &msg, int32_t err) {
    sp<AReplyToken> replyID;
    CHECK(msg->senderAwaitsResponse(&replyID));
    PostReplyWithError(replyID, err);
}

void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
    int32_t finalErr = err;
    if (mReleasedByResourceManager) {
@@ -1511,7 +1517,6 @@ status_t MediaCodec::reset() {
    mStickyError = OK;

    // reset state not reset by setState(UNINITIALIZED)
    mReplyID = 0;
    mDequeueInputReplyID = 0;
    mDequeueOutputReplyID = 0;
    mDequeueInputTimeoutGeneration = 0;
@@ -2159,7 +2164,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                if (mState == RELEASING) {
                                    mComponentName.clear();
                                }
                                (new AMessage)->postReply(mReplyID);
                                postPendingRepliesAndDeferredMessages();
                                sendErrorResponse = false;
                            }
                            break;
@@ -2185,7 +2190,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        case FLUSHED:
                        case STARTED:
                        {
                            sendErrorResponse = false;
                            sendErrorResponse = (mReplyID != nullptr);

                            setStickyError(err);
                            postActivityNotificationIfPossible();
@@ -2215,7 +2220,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

                        default:
                        {
                            sendErrorResponse = false;
                            sendErrorResponse = (mReplyID != nullptr);

                            setStickyError(err);
                            postActivityNotificationIfPossible();
@@ -2242,7 +2247,15 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    }

                    if (sendErrorResponse) {
                        PostReplyWithError(mReplyID, err);
                        // TRICKY: replicate PostReplyWithError logic for
                        //         err code override
                        int32_t finalErr = err;
                        if (mReleasedByResourceManager) {
                            // override the err code if MediaCodec has been
                            // released by ResourceManager.
                            finalErr = DEAD_OBJECT;
                        }
                        postPendingRepliesAndDeferredMessages(finalErr);
                    }
                    break;
                }
@@ -2290,7 +2303,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                MediaResource::CodecResource(mFlags & kFlagIsSecure, mIsVideo));
                    }

                    (new AMessage)->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages();
                    break;
                }

@@ -2329,7 +2342,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        mFlags |= kFlagUsesSoftwareRenderer;
                    }
                    setState(CONFIGURED);
                    (new AMessage)->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages();

                    // augment our media metrics info, now that we know more things
                    // such as what the codec extracted from any CSD passed in.
@@ -2374,6 +2387,12 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

                case kWhatInputSurfaceCreated:
                {
                    if (mState != CONFIGURED) {
                        // state transitioned unexpectedly; we should have replied already.
                        ALOGD("received kWhatInputSurfaceCreated message in state %s",
                                stateString(mState).c_str());
                        break;
                    }
                    // response to initiateCreateInputSurface()
                    status_t err = NO_ERROR;
                    sp<AMessage> response = new AMessage;
@@ -2392,12 +2411,18 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    } else {
                        response->setInt32("err", err);
                    }
                    response->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages(response);
                    break;
                }

                case kWhatInputSurfaceAccepted:
                {
                    if (mState != CONFIGURED) {
                        // state transitioned unexpectedly; we should have replied already.
                        ALOGD("received kWhatInputSurfaceAccepted message in state %s",
                                stateString(mState).c_str());
                        break;
                    }
                    // response to initiateSetInputSurface()
                    status_t err = NO_ERROR;
                    sp<AMessage> response = new AMessage();
@@ -2408,19 +2433,25 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    } else {
                        response->setInt32("err", err);
                    }
                    response->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages(response);
                    break;
                }

                case kWhatSignaledInputEOS:
                {
                    if (!isExecuting()) {
                        // state transitioned unexpectedly; we should have replied already.
                        ALOGD("received kWhatSignaledInputEOS message in state %s",
                                stateString(mState).c_str());
                        break;
                    }
                    // response to signalEndOfInputStream()
                    sp<AMessage> response = new AMessage;
                    status_t err;
                    if (msg->findInt32("err", &err)) {
                        response->setInt32("err", err);
                    }
                    response->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages(response);
                    break;
                }

@@ -2439,7 +2470,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                MediaResource::GraphicMemoryResource(getGraphicBufferSize()));
                    }
                    setState(STARTED);
                    (new AMessage)->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages();
                    break;
                }

@@ -2669,7 +2700,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        break;
                    }
                    setState(INITIALIZED);
                    (new AMessage)->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages();
                    break;
                }

@@ -2693,7 +2724,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    mReleaseSurface.reset();

                    if (mReplyID != nullptr) {
                        (new AMessage)->postReply(mReplyID);
                        postPendingRepliesAndDeferredMessages();
                    }
                    if (mAsyncReleaseCompleteNotification != nullptr) {
                        flushMediametrics();
@@ -2718,7 +2749,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        mCodec->signalResume();
                    }

                    (new AMessage)->postReply(mReplyID);
                    postPendingRepliesAndDeferredMessages();
                    break;
                }

@@ -2730,14 +2761,18 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatInit:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            if (mState != UNINITIALIZED) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            mReplyID = replyID;
            setState(INITIALIZING);

@@ -2799,13 +2834,17 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatConfigure:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            if (mState != INITIALIZED) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            sp<RefBase> obj;
            CHECK(msg->findObject("surface", &obj));
@@ -2944,14 +2983,18 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
        case kWhatCreateInputSurface:
        case kWhatSetInputSurface:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            // Must be configured, but can't have been started yet.
            if (mState != CONFIGURED) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            mReplyID = replyID;
            if (msg->what() == kWhatCreateInputSurface) {
@@ -2967,9 +3010,6 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
        }
        case kWhatStart:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            if (mState == FLUSHED) {
                setState(STARTED);
                if (mHavePendingInputBuffers) {
@@ -2977,12 +3017,19 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    mHavePendingInputBuffers = false;
                }
                mCodec->signalResume();
                PostReplyWithError(replyID, OK);
                PostReplyWithError(msg, OK);
                break;
            } else if (mState != CONFIGURED) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            mReplyID = replyID;
            setState(STARTING);
@@ -2991,15 +3038,42 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatStop:
        case kWhatStop: {
            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            [[fallthrough]];
        }
        case kWhatRelease:
        {
            State targetState =
                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;

            if ((mState == RELEASING && targetState == UNINITIALIZED)
                    || (mState == STOPPING && targetState == INITIALIZED)) {
                mDeferredMessages.push_back(msg);
                break;
            }

            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            sp<AMessage> asyncNotify;
            (void)msg->findMessage("async", &asyncNotify);
            // post asyncNotify if going out of scope.
            struct AsyncNotifyPost {
                AsyncNotifyPost(const sp<AMessage> &asyncNotify) : mAsyncNotify(asyncNotify) {}
                ~AsyncNotifyPost() {
                    if (mAsyncNotify) {
                        mAsyncNotify->post();
                    }
                }
                void clear() { mAsyncNotify.clear(); }
            private:
                sp<AMessage> mAsyncNotify;
            } asyncNotifyPost{asyncNotify};

            // already stopped/released
            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
                sp<AMessage> response = new AMessage;
@@ -3063,12 +3137,14 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            // after this, and we'll no longer be able to reply.
            if (mState == FLUSHING || mState == STOPPING
                    || mState == CONFIGURING || mState == STARTING) {
                (new AMessage)->postReply(mReplyID);
                // mReply is always set if in these states.
                postPendingRepliesAndDeferredMessages();
            }

            if (mFlags & kFlagSawMediaServerDie) {
                // It's dead, Jim. Don't expect initiateShutdown to yield
                // any useful results now...
                // Any pending reply would have been handled at kWhatError.
                setState(UNINITIALIZED);
                if (targetState == UNINITIALIZED) {
                    mComponentName.clear();
@@ -3082,12 +3158,12 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            // reply now with an error to unblock the client, client can
            // release after the failure (instead of ANR).
            if (msg->what() == kWhatStop && (mFlags & kFlagStickyError)) {
                // Any pending reply would have been handled at kWhatError.
                PostReplyWithError(replyID, getStickyError());
                break;
            }

            sp<AMessage> asyncNotify;
            if (msg->findMessage("async", &asyncNotify) && asyncNotify != nullptr) {
            if (asyncNotify != nullptr) {
                if (mSurface != NULL) {
                    if (!mReleaseSurface) {
                        mReleaseSurface.reset(new ReleaseSurface);
@@ -3107,6 +3183,12 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                }
            }

            if (mReplyID) {
                // State transition replies are handled above, so this reply
                // would not be related to state transition. As we are
                // shutting down the component, just fail the operation.
                postPendingRepliesAndDeferredMessages(UNKNOWN_ERROR);
            }
            mReplyID = replyID;
            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);

@@ -3121,8 +3203,8 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

            if (asyncNotify != nullptr) {
                mResourceManagerProxy->markClientForPendingRemoval();
                (new AMessage)->postReply(mReplyID);
                mReplyID = 0;
                postPendingRepliesAndDeferredMessages();
                asyncNotifyPost.clear();
                mAsyncReleaseCompleteNotification = asyncNotify;
            }

@@ -3293,17 +3375,21 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatSignalEndOfInputStream:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            if (!isExecuting() || !mHaveInputSurface) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            } else if (mFlags & kFlagStickyError) {
                PostReplyWithError(replyID, getStickyError());
                PostReplyWithError(msg, getStickyError());
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            mReplyID = replyID;
            mCodec->signalEndOfInputStream();
            break;
@@ -3345,16 +3431,20 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatFlush:
        {
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            if (!isExecuting()) {
                PostReplyWithError(replyID, INVALID_OPERATION);
                PostReplyWithError(msg, INVALID_OPERATION);
                break;
            } else if (mFlags & kFlagStickyError) {
                PostReplyWithError(replyID, getStickyError());
                PostReplyWithError(msg, getStickyError());
                break;
            }

            if (mReplyID) {
                mDeferredMessages.push_back(msg);
                break;
            }
            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));

            mReplyID = replyID;
            // TODO: skip flushing if already FLUSHED
@@ -4188,6 +4278,26 @@ status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
    return OK;
}

void MediaCodec::postPendingRepliesAndDeferredMessages(status_t err /* = OK */) {
    sp<AMessage> response{new AMessage};
    if (err != OK) {
        response->setInt32("err", err);
    }
    postPendingRepliesAndDeferredMessages(response);
}

void MediaCodec::postPendingRepliesAndDeferredMessages(const sp<AMessage> &response) {
    CHECK(mReplyID);
    response->postReply(mReplyID);
    mReplyID.clear();
    ALOGV_IF(!mDeferredMessages.empty(),
            "posting %zu deferred messages", mDeferredMessages.size());
    for (sp<AMessage> msg : mDeferredMessages) {
        msg->post();
    }
    mDeferredMessages.clear();
}

std::string MediaCodec::stateString(State state) {
    const char *rval = NULL;
    char rawbuffer[16]; // room for "%d"
+5 −0
Original line number Diff line number Diff line
@@ -366,6 +366,7 @@ private:
    AString mOwnerName;
    sp<MediaCodecInfo> mCodecInfo;
    sp<AReplyToken> mReplyID;
    std::vector<sp<AMessage>> mDeferredMessages;
    uint32_t mFlags;
    status_t mStickyError;
    sp<Surface> mSurface;
@@ -435,6 +436,7 @@ private:
    static status_t PostAndAwaitResponse(
            const sp<AMessage> &msg, sp<AMessage> *response);

    void PostReplyWithError(const sp<AMessage> &msg, int32_t err);
    void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);

    status_t init(const AString &name);
@@ -484,6 +486,9 @@ private:
    bool hasPendingBuffer(int portIndex);
    bool hasPendingBuffer();

    void postPendingRepliesAndDeferredMessages(status_t err = OK);
    void postPendingRepliesAndDeferredMessages(const sp<AMessage> &response);

    /* called to get the last codec error when the sticky flag is set.
     * if no such codec error is found, returns UNKNOWN_ERROR.
     */