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

Commit 0435f125 authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge "Error handling when looper is different for the getChoreographer than originally sourced."

parents 58101399 2cf250c0
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -366,6 +366,14 @@ public final class Choreographer {
        dispose();
    }

    /**
     * Check if the sourced looper and the current looper are same.
     * @hide
     */
    boolean isTheLooperSame(Looper looper) {
        return mLooper == looper;
    }

    /**
     * The amount of time, in milliseconds, between each frame of the animation.
     * <p>
+26 −16
Original line number Diff line number Diff line
@@ -1317,27 +1317,36 @@ public final class SurfaceControl implements Parcelable {
    }

    /**
     * Returns the associated {@link Choreographer} instance with the
     * current instance of the SurfaceControl.
     * Must be called from a thread that already has a {@link android.os.Looper}
     * associated with it.
     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
     * of the {@link Choreographer} is created.
     * When called for the first time a new instance of the {@link Choreographer} is created
     * with a {@link android.os.Looper} of the current thread. Every subsequent call will return
     * the same instance of the Choreographer.
     *
     * @see #getChoreographer(Looper) to create Choreographer with a different
     * looper than current thread looper.
     *
     * @hide
     */
    @TestApi
    public @NonNull Choreographer getChoreographer() {
        checkNotReleased();
        synchronized (mChoreographerLock) {
            if (mChoreographer == null) {
                return getChoreographer(Looper.myLooper());
            }
            return mChoreographer;
        }
    }

    /**
     * Returns the associated {@link Choreographer} instance with the
     * current instance of the SurfaceControl.
     * If there is no {@link Choreographer} associated with the SurfaceControl then a new instance
     * of the {@link Choreographer} is created.
     * When called for the first time a new instance of the {@link Choreographer} is created with
     * the sourced {@link android.os.Looper}. Every subsequent call will return the same
     * instance of the Choreographer.
     *
     * @see #getChoreographer()
     *
     * @param looper the choreographer is attached on this looper
     * @throws IllegalStateException when a {@link Choreographer} instance exists with a different
     * looper than sourced.
     * @param looper the choreographer is attached on this looper.
     *
     * @hide
     */
@@ -1345,11 +1354,12 @@ public final class SurfaceControl implements Parcelable {
    public @NonNull Choreographer getChoreographer(@NonNull Looper looper) {
        checkNotReleased();
        synchronized (mChoreographerLock) {
            if (mChoreographer != null) {
                return mChoreographer;
            }

            if (mChoreographer == null) {
                mChoreographer = Choreographer.getInstanceForSurfaceControl(mNativeHandle, looper);
            } else if (!mChoreographer.isTheLooperSame(looper)) {
                throw new IllegalStateException(
                        "Choreographer already exists with a different looper");
            }
            return mChoreographer;
        }
    }
+31 −5
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package android.view.choreographertests;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -63,6 +65,7 @@ public class AttachedChoreographerTest {
    private DisplayManager mDisplayManager;
    private SurfaceView mSurfaceView;
    private SurfaceHolder mSurfaceHolder;
    private Choreographer mChoreographer;
    private boolean mIsFirstCallback = true;
    private int mCallbackMissedCounter = 0;

@@ -127,37 +130,60 @@ public class AttachedChoreographerTest {

    @Test
    public void testCreateChoreographer() {
        Looper testLooper = Looper.myLooper();
        mScenario.onActivity(activity -> {
            if (waitForCountDown(mSurfaceCreationCountDown, /* timeoutInSeconds */ 1L)) {
                fail("Unable to create surface within 1 Second");
            }
            SurfaceControl sc = mSurfaceView.getSurfaceControl();
            mChoreographer = sc.getChoreographer();
            mTestCompleteSignal.countDown();
            SurfaceControl sc1 = new SurfaceControl(sc, "AttachedChoreographerTests");
            // Create attached choreographer with getChoreographer
            sc1.getChoreographer();
            Choreographer choreographer1 = sc1.getChoreographer();
            assertTrue(sc1.hasChoreographer());
            assertTrue(sc1.isValid());
            sc1.release();
            assertEquals(choreographer1, sc1.getChoreographer());
            assertEquals(choreographer1, sc1.getChoreographer(Looper.myLooper()));
            assertEquals(choreographer1, sc1.getChoreographer(Looper.getMainLooper()));
            assertThrows(IllegalStateException.class, () -> sc1.getChoreographer(testLooper));

            SurfaceControl sc2 = new SurfaceControl(sc, "AttachedChoreographerTests");
            // Create attached choreographer with Looper.myLooper
            sc2.getChoreographer(Looper.myLooper());
            Choreographer choreographer2 = sc2.getChoreographer(Looper.myLooper());
            assertTrue(sc2.hasChoreographer());
            assertTrue(sc2.isValid());
            sc2.release();
            assertEquals(choreographer2, sc2.getChoreographer(Looper.myLooper()));
            assertEquals(choreographer2, sc2.getChoreographer(Looper.getMainLooper()));
            assertEquals(choreographer2, sc2.getChoreographer());
            assertThrows(IllegalStateException.class, () -> sc2.getChoreographer(testLooper));

            SurfaceControl sc3 = new SurfaceControl(sc, "AttachedChoreographerTests");
            // Create attached choreographer with Looper.myLooper
            sc3.getChoreographer(Looper.getMainLooper());
            Choreographer choreographer3 = sc3.getChoreographer(Looper.getMainLooper());
            assertTrue(sc3.hasChoreographer());
            assertTrue(sc3.isValid());
            assertEquals(choreographer3, sc3.getChoreographer(Looper.getMainLooper()));
            assertEquals(choreographer3, sc3.getChoreographer(Looper.myLooper()));
            assertEquals(choreographer3, sc3.getChoreographer());
            assertThrows(IllegalStateException.class, () -> sc3.getChoreographer(testLooper));

            assertNotEquals(choreographer1, choreographer2);
            assertNotEquals(choreographer1, choreographer3);
            assertNotEquals(choreographer2, choreographer3);
            sc1.release();
            sc2.release();
            sc3.release();
            mTestCompleteSignal.countDown();
        });
        if (waitForCountDown(mTestCompleteSignal, /* timeoutInSeconds */ 2L)) {
            fail("Test not finished in 2 Seconds");
        }
        SurfaceControl surfaceControl = mSurfaceView.getSurfaceControl();
        assertTrue(surfaceControl.hasChoreographer());
        assertEquals(mChoreographer, surfaceControl.getChoreographer());
        assertThrows(IllegalStateException.class,
                () -> surfaceControl.getChoreographer(testLooper));
    }

    @Test