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

Commit 00198246 authored by Wonsik Kim's avatar Wonsik Kim Committed by Automerger Merge Worker
Browse files

Merge "MediaCodec: fix crash at codec service death while releaseAsync" am:...

Merge "MediaCodec: fix crash at codec service death while releaseAsync" am: baba96a5 am: b68c47f7

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

Change-Id: I83b36e94d783a7f5938752084e5cafe1fab9b6b1
parents fc010195 b68c47f7
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -2283,6 +2283,11 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        case STOPPING:
                        {
                            if (mFlags & kFlagSawMediaServerDie) {
                                bool postPendingReplies = true;
                                if (mState == RELEASING && !mReplyID) {
                                    ALOGD("Releasing asynchronously, so nothing to reply here.");
                                    postPendingReplies = false;
                                }
                                // MediaServer died, there definitely won't
                                // be a shutdown complete notification after
                                // all.
@@ -2294,7 +2299,9 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                                if (mState == RELEASING) {
                                    mComponentName.clear();
                                }
                                if (postPendingReplies) {
                                    postPendingRepliesAndDeferredMessages(origin + ":dead");
                                }
                                sendErrorResponse = false;
                            } else if (!mReplyID) {
                                sendErrorResponse = false;
+44 −0
Original line number Diff line number Diff line
@@ -349,3 +349,47 @@ TEST(MediaCodecTest, ErrorWhileStopping) {
    codec->release();
    looper->stop();
}

TEST(MediaCodecTest, DeadWhileAsyncReleasing) {
    // Test scenario:
    //
    // 1) Client thread calls release(); MediaCodec looper thread calls
    //    initiateShutdown(); shutdown is being handled at the component thread.
    // 2) Codec service died during the shutdown operation.
    // 3) MediaCodec looper thread handles the death.

    static const AString kCodecName{"test.codec"};
    static const AString kCodecOwner{"nobody"};
    static const AString kMediaType{"video/x-test"};

    sp<MockCodec> mockCodec;
    std::function<sp<CodecBase>(const AString &name, const char *owner)> getCodecBase =
        [&mockCodec](const AString &, const char *) {
            mockCodec = new MockCodec([](const std::shared_ptr<MockBufferChannel> &) {
                // No mock setup, as we don't expect any buffer operations
                // in this scenario.
            });
            ON_CALL(*mockCodec, initiateAllocateComponent(_))
                .WillByDefault([mockCodec](const sp<AMessage> &) {
                    mockCodec->callback()->onComponentAllocated(kCodecName.c_str());
                });
            ON_CALL(*mockCodec, initiateShutdown(_))
                .WillByDefault([mockCodec](bool) {
                    // 2)
                    mockCodec->callback()->onError(DEAD_OBJECT, ACTION_CODE_FATAL);
                    // Codec service has died, no callback.
                });
            return mockCodec;
        };

    sp<ALooper> looper{new ALooper};
    sp<MediaCodec> codec = SetupMediaCodec(
            kCodecOwner, kCodecName, kMediaType, looper, getCodecBase);
    ASSERT_NE(nullptr, codec) << "Codec must not be null";
    ASSERT_NE(nullptr, mockCodec) << "MockCodec must not be null";

    codec->releaseAsync(new AMessage);
    // sleep here so that the looper thread can handle the error
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    looper->stop();
}