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

Commit 762ac978 authored by Kean Mariotti's avatar Kean Mariotti
Browse files

viewcapture: guarantee happens-before relationship

Turn ViewPropertyRef#captured into a volatile field to rule out a
possibly missing happens-before relationship, which could explain
the null pointer exceptions observed in b/375005884.

The main thread's write and the bg thread's read of the volatile field
become a synchronization point across which prior main thread's writes
and subsequent bg thread's reads cannot be reordered.

This ensures that bg thread is observing all the main thread's writes
performed on the ViewPropertyRef instances passed from main to bg.

Bug: 375005884
Flag: EXEMPT bugfix
Test: enable viewcapture on sysui windows and check the NPE \
	doesn't happen anymore on presubmit
Change-Id: I0329fb563657a9e355099feda7d89c24771ae4d4
parent 58b1c86c
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -311,8 +311,12 @@ public abstract class ViewCapture {
            captureViewTree(mRoot, mViewPropertyRef);
            ViewPropertyRef captured = mViewPropertyRef.next;
            if (captured != null) {
                captured.callback = mCaptureCallback;
                captured.elapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();

                // Main thread writes volatile field:
                // guarantee that variable changes prior the field write are visible to bg thread
                captured.volatileCallback = mCaptureCallback;

                mBgExecutor.execute(captured);
            }
            mIsFirstFrame = false;
@@ -552,9 +556,11 @@ public abstract class ViewCapture {

        public ViewPropertyRef next;

        public Consumer<ViewPropertyRef> callback = null;
        public long elapsedRealtimeNanos = 0;

        // Volatile field to establish happens-before relationship between main and bg threads
        // (see JSR-133: Java Memory Model and Thread Specification)
        public volatile Consumer<ViewPropertyRef> volatileCallback = null;

        public void transferFrom(View in) {
            view = in;
@@ -651,8 +657,10 @@ public abstract class ViewCapture {

        @Override
        public void run() {
            Consumer<ViewPropertyRef> oldCallback = callback;
            callback = null;
            // Bg thread reads volatile field:
            // guarantee that variable changes in main thread prior the field write are visible
            Consumer<ViewPropertyRef> oldCallback = volatileCallback;
            volatileCallback = null;
            if (oldCallback != null) {
                oldCallback.accept(this);
            }