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

Commit dd6524d4 authored by Arun Johnson's avatar Arun Johnson
Browse files

CryptoAsync: discarding buffers during flush

 - discards pending buffers during flush and also
   reset the message loop after flush to prevent
   unnecessary message loop

Bug: 362450802
Test: atest android.media.drmframework.cts.MediaDrmCodecCryptoAsyncTest
Flag: EXEMPT bugfix

Change-Id: I29cc3037e3e37241c64a1e61d1415bdf082aecfd
parent ab06c186
Loading
Loading
Loading
Loading
+18 −16
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ status_t CryptoAsync::decrypt(sp<AMessage> &msg) {
       return -ENOSYS;
    }
    bool shouldPost = false;
    msg->setWhat(kWhatDecrypt);
    Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
    if (mState != kCryptoAsyncActive) {
       ALOGE("Cannot decrypt in errored state");
@@ -241,18 +242,16 @@ void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
                pendingBuffers->pop_front();
                continue;
            }
            nextTask = kWhatDecrypt;
            nextTask = nextBuffer->what();
        }
        return OK;
    };
    sp<AMessage> thisMsg;
    uint32_t nextTask = kWhatDoNothing;
    getCurrentAndNextTask(&thisMsg, nextTask);
    switch(msg->what()) {
        case kWhatDecrypt:
        {
            sp<AMessage> thisMsg;
            uint32_t nextTask = kWhatDoNothing;
            if(OK != getCurrentAndNextTask(&thisMsg, nextTask)) {
                return;
            }
            if (thisMsg != nullptr) {
                int32_t action;
                err = OK;
@@ -280,15 +279,6 @@ void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
                    mState = kCryptoAsyncError;
                }
            }
            // we won't take  next buffers if buffer caused
            // an error. We want the caller to deal with the error first
            // Expected behahiour is that the caller acknowledge the error
            // with a call to stop() which clear the queues.
            // Then move forward with processing of next set of buffers.
            if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
                sp<AMessage> nextMsg = new AMessage(nextTask,this);
                nextMsg->post();
            }
            break;
        }

@@ -306,10 +296,13 @@ void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
                returnList->splice(returnList->end(), std::move(*pendingBuffers));
            }
            pendingBuffers->clear();
            // stop() is a blocking call.
            // this is needed as the queue is cleared now and there should
            // not be any next task. The next buffer when queued will kick off this loop
            nextTask = kWhatDoNothing;
            mState = kCryptoAsyncActive;
            response->setInt32("err", OK);
            response->postReply(replyID);

            break;
        }

@@ -321,6 +314,15 @@ void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
            break;
        }
    }
    // we won't take  next buffers if buffer caused
    // an error. We want the caller to deal with the error first
    // Expected behahiour is that the caller acknowledge the error
    // with a call to stop() which clear the queues.
    // Then move forward with processing of next set of buffers.
    if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
        sp<AMessage> nextMsg = new AMessage(nextTask,this);
        nextMsg->post();
    }
}

}  // namespace android
+19 −13
Original line number Diff line number Diff line
@@ -4298,6 +4298,21 @@ inline void MediaCodec::initClientConfigParcel(ClientConfigParcel& clientConfig)
    clientConfig.id = mCodecId;
}

void MediaCodec::stopCryptoAsync() {
    if (mCryptoAsync) {
        sp<RefBase> obj;
        sp<MediaCodecBuffer> buffer;
        std::list<sp<AMessage>> stalebuffers;
        mCryptoAsync->stop(&stalebuffers);
        for (sp<AMessage> &msg : stalebuffers) {
            if (msg->findObject("buffer", &obj)) {
                buffer = decltype(buffer.get())(obj.get());
                mBufferChannel->discardBuffer(buffer);
            }
        }
    }
}

void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatCodecNotify:
@@ -4330,10 +4345,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    }
                    codecErrorState = kCodecErrorState;
                    origin += stateString(mState);
                    if (mCryptoAsync) {
                        //TODO: do some book keeping on the buffers
                        mCryptoAsync->stop();
                    }
                    stopCryptoAsync();
                    switch (mState) {
                        case INITIALIZING:
                        {
@@ -5630,9 +5642,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {

            sp<AReplyToken> replyID;
            CHECK(msg->senderAwaitsResponse(&replyID));
            if (mCryptoAsync) {
                mCryptoAsync->stop();
            }
            stopCryptoAsync();
            sp<AMessage> asyncNotify;
            (void)msg->findMessage("async", &asyncNotify);
            // post asyncNotify if going out of scope.
@@ -6100,11 +6110,7 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
            mReplyID = replyID;
            // TODO: skip flushing if already FLUSHED
            setState(FLUSHING);
            if (mCryptoAsync) {
                std::list<sp<AMessage>> pendingBuffers;
                mCryptoAsync->stop(&pendingBuffers);
                //TODO: do something with these buffers
            }
            stopCryptoAsync();
            mCodec->signalFlush();
            returnBuffersToCodec();
            TunnelPeekState previousState = mTunnelPeekState;
@@ -6932,7 +6938,7 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
            // prepare a message and enqueue
            sp<AMessage> cryptoInfo = new AMessage();
            buildCryptoInfoAMessage(cryptoInfo, CryptoAsync::kActionDecrypt);
            mCryptoAsync->decrypt(cryptoInfo);
            err = mCryptoAsync->decrypt(cryptoInfo);
        } else if (msg->findObject("cryptoInfos", &obj)) {
                buffer->meta()->setObject("cryptoInfos", obj);
                err = mBufferChannel->queueSecureInputBuffers(
+2 −0
Original line number Diff line number Diff line
@@ -757,6 +757,8 @@ private:

    void onReleaseCrypto(const sp<AMessage>& msg);

    void stopCryptoAsync();

    // managing time-of-flight aka latency
    typedef struct {
            int64_t presentationUs;