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

Commit 89f28270 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Fix ViewRootImpl traversal issue after SurfaceSyncGroup timeout

ViewRootImpl traversal is blocked from the time a sync is requested
to when the sync is successfully added to a SurfaceSyncGroup.
If the ViewRootImpl draw timeouts, the ViewRootImpl's
SurfaceSyncGroup is marked as ready. If there is another
sync request on the ViewRootImpl before the traversal path,
we can get in a state where we will never draw again.

Fix this by updating cleaning up the ViewRootImpl state
when the SurfaceSyncGroup is marked as ready.

Flag: EXEMPT bug fix
Bug: 362513091
Test: presubmit (coming in future cl)
Change-Id: I6c0ac8f96914d231cc9dc695f6fc8975ba2c5864
parent 0c06c085
Loading
Loading
Loading
Loading
+33 −8
Original line number Diff line number Diff line
@@ -6971,9 +6971,7 @@ public final class ViewRootImpl implements ViewParent,
                    handleScrollCaptureRequest((IScrollCaptureResponseListener) msg.obj);
                    break;
                case MSG_PAUSED_FOR_SYNC_TIMEOUT:
                    Log.e(mTag, "Timedout waiting to unpause for sync");
                    mNumPausedForSync = 0;
                    scheduleTraversals();
                    resumeAfterSyncTimeout();
                    break;
                case MSG_CHECK_INVALIDATION_IDLE: {
                    long delta;
@@ -12766,6 +12764,15 @@ public final class ViewRootImpl implements ViewParent,
        activeSurfaceSyncGroup.addTransaction(t);
    }
    /**
     * Resume rendering after being paused for sync due to a timeout.
     */
    private void resumeAfterSyncTimeout() {
        Log.e(mTag, "Timedout waiting to unpause for sync mNumPausedForSync=" + mNumPausedForSync);
        mNumPausedForSync = 0;
        scheduleTraversals();
    }
    @Override
    public SurfaceSyncGroup getOrCreateSurfaceSyncGroup() {
        boolean newSyncGroup = false;
@@ -12793,6 +12800,16 @@ public final class ViewRootImpl implements ViewParent,
                }
            });
            newSyncGroup = true;
            // If the sync group is marked ready by a timeout, check if rendering is paused and
            // if it is, resume rendering and trigger a traversal.
            mActiveSurfaceSyncGroup.addSyncCompleteCallback(mExecutor, () -> {
                if (mActiveSurfaceSyncGroup != null
                        && mActiveSurfaceSyncGroup.isComplete() && mNumPausedForSync > 0) {
                    mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT);
                    resumeAfterSyncTimeout();
                }
            });
        }
        Trace.instant(Trace.TRACE_TAG_VIEW,
@@ -12807,12 +12824,20 @@ public final class ViewRootImpl implements ViewParent,
            }
        }
        // The sync group can be marked ready by a timeout. This makes incrementing
        // mNumPausedForSync racy. Here we check if the sync group is complete and
        // if it is then we don't pause for syncing.
        if (!mActiveSurfaceSyncGroup.isComplete()) {
            mNumPausedForSync++;
            mHandler.removeMessages(MSG_PAUSED_FOR_SYNC_TIMEOUT);
            mHandler.sendEmptyMessageDelayed(MSG_PAUSED_FOR_SYNC_TIMEOUT,
                    1000 * Build.HW_TIMEOUT_MULTIPLIER);
        } else {
            Log.d(mTag, "Active sync group is already completed "
                    + mActiveSurfaceSyncGroup.getName());
        }
        return mActiveSurfaceSyncGroup;
    };
    }
    private final Executor mSimpleExecutor = Runnable::run;
+10 −0
Original line number Diff line number Diff line
@@ -838,6 +838,16 @@ public final class SurfaceSyncGroup {
        mHandler.postDelayed(runnable, this, TRANSACTION_READY_TIMEOUT);
    }

    /**
     * Returns true if the SurfaceSyncGroup has completed its sync.
     * @hide
     */
    public boolean isComplete() {
        synchronized (mLock) {
            return mFinished;
        }
    }

    /**
     * A frame callback that is used to synchronize SurfaceViews. The owner of the SurfaceView must
     * implement onFrameStarted when trying to sync the SurfaceView. This is to ensure the sync