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

Commit 2b407e5b authored by Shuzhen Wang's avatar Shuzhen Wang
Browse files

Camera: Flush all state transitions before reconfigureCamera

Pending ACTIVE<->IDLE states transitions may be queued in StatusTracker.

It's possible that the camera device has transitioned from IDLE to
ACTIVE, but StatusTracker hasn't called notifyStatus(ACTIVE) when
reconfigureCamera() is called.

Solution is to flush the statusTracker before reconfigureCamera().

Test: Camera CTS, vendor testing
Bug: 289974845
Change-Id: I4ceb96b855113cc7e042682df344df6481124997
Merged-In: I4ceb96b855113cc7e042682df344df6481124997
parent efa8c657
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2336,6 +2336,9 @@ bool Camera3Device::reconfigureCamera(const CameraMetadata& sessionParams, int c
    // deadlocks (http://b/143513518)
    nsecs_t maxExpectedDuration = getExpectedInFlightDuration();

    // Make sure status tracker is flushed
    mStatusTracker->flushPendingStates();

    Mutex::Autolock l(mLock);
    if (checkAbandonedStreamsLocked()) {
        ALOGW("%s: Abandoned stream detected, session parameters can't be applied correctly!",
+39 −9
Original line number Diff line number Diff line
@@ -34,7 +34,8 @@ StatusTracker::StatusTracker(wp<Camera3Device> parent) :
        mParent(parent),
        mNextComponentId(0),
        mIdleFence(new Fence()),
        mDeviceState(IDLE) {
        mDeviceState(IDLE),
        mFlushed(true) {
}

StatusTracker::~StatusTracker() {
@@ -111,6 +112,15 @@ void StatusTracker::markComponent(int id, ComponentState state,
        const sp<Fence>& componentFence) {
    ALOGV("%s: Component %d is now %s", __FUNCTION__, id,
            state == IDLE ? "idle" : "active");

    // If any component state changes, the status tracker is considered
    // not flushed.
    {
        Mutex::Autolock l(mFlushLock);
        mFlushed = false;
    }

    {
        Mutex::Autolock l(mPendingLock);

        StateChange newState = {
@@ -122,12 +132,21 @@ void StatusTracker::markComponent(int id, ComponentState state,
        mPendingChangeQueue.add(newState);
        mPendingChangeSignal.signal();
    }
}

void StatusTracker::flushPendingStates()  {
    Mutex::Autolock l(mFlushLock);
    while (!mFlushed && isRunning()) {
        mFlushCondition.waitRelative(mFlushLock, kWaitDuration);
    }
}

void StatusTracker::requestExit() {
    // First mark thread dead
    Thread::requestExit();
    // Then exit any waits
    mPendingChangeSignal.signal();
    mFlushCondition.signal();
}

StatusTracker::ComponentState StatusTracker::getDeviceStateLocked() {
@@ -227,6 +246,17 @@ bool StatusTracker::threadLoop() {
    }
    mStateTransitions.clear();

    // After all pending changes are cleared and notified, mark the tracker
    // as flushed.
    {
        Mutex::Autolock fl(mFlushLock);
        Mutex::Autolock pl(mPendingLock);
        if (mPendingChangeQueue.size() == 0) {
            mFlushed = true;
            mFlushCondition.signal();
        }
    }

    return true;
}

+9 −0
Original line number Diff line number Diff line
@@ -70,6 +70,10 @@ class StatusTracker: public Thread {

    void dumpActiveComponents();

    // Flush all pending states inflight in the tracker, and return upon
    // completion.
    void flushPendingStates();

    virtual void requestExit();
  protected:

@@ -113,6 +117,11 @@ class StatusTracker: public Thread {
    // Current overall device state
    ComponentState mDeviceState;

    // For flushing all pending states transitions
    bool mFlushed;
    Mutex mFlushLock;
    Condition mFlushCondition;

    // Private to threadLoop

    // Determine current overall device state