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

Commit 49230c42 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

Add surface changed callbacks to ViewRootImpl

Allow SurfaceView to be notified when the ViewRootImpl surface changes, is created or
destroyed. The callbacks include a SurfaceControl Transaction object which can be used to
synchronize SurfaceControl changes by the system.

In particular, the transaction will be used to update the relative z order of the SurfaceView
surface when the ViewRootImpl surface changes. WMS is responsible for providing ViewRootImpl a
new surface as well as reparenting its children (SurfaceViews). The transaction will be applied by
the service when it is ready to show the new surface, synchronizing the reparenting with the
relative z update.

Bug: 132205507
Test: go/wm-smoke
Change-Id: Ie5aed430d09cc6d3a0a99f618094b3a50dbaa5cc
parent d387b1b2
Loading
Loading
Loading
Loading
+113 −51
Original line number Diff line number Diff line
@@ -477,6 +477,12 @@ public final class ViewRootImpl implements ViewParent,
    public final Surface mSurface = new Surface();
    private final SurfaceControl mSurfaceControl = new SurfaceControl();

    /**
     * Transaction object that can be used to synchronize child SurfaceControl changes with
     * ViewRootImpl SurfaceControl changes by the server. The object is passed along with
     * the SurfaceChangedCallback.
     */
    private final Transaction mSurfaceChangedTransaction = new Transaction();
    /**
     * Child surface of {@code mSurface} with the same bounds as its parent, and crop bounds
     * are set to the parent's bounds adjusted for surface insets. This surface is created when
@@ -1577,7 +1583,10 @@ public final class ViewRootImpl implements ViewParent,
            }

            if (mStopped) {
                if (mSurfaceHolder != null && mSurface.isValid()) {
                if (mSurface.isValid()) {
                    if (mSurfaceHolder != null) {
                        notifyHolderSurfaceDestroyed();
                    }
                    notifySurfaceDestroyed();
                }
                destroySurface();
@@ -1585,6 +1594,46 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    /** Register callbacks to be notified when the ViewRootImpl surface changes. */
    interface SurfaceChangedCallback {
        void surfaceCreated(Transaction t);
        void surfaceReplaced(Transaction t);
        void surfaceDestroyed();
    }

    private final ArrayList<SurfaceChangedCallback> mSurfaceChangedCallbacks = new ArrayList<>();
    void addSurfaceChangedCallback(SurfaceChangedCallback c) {
        mSurfaceChangedCallbacks.add(c);
    }

    void removeSurfaceChangedCallback(SurfaceChangedCallback c) {
        mSurfaceChangedCallbacks.remove(c);
    }

    private void notifySurfaceCreated() {
        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
            mSurfaceChangedCallbacks.get(i).surfaceCreated(mSurfaceChangedTransaction);
        }
    }

    /**
     * Notify listeners when the ViewRootImpl surface has been replaced. This callback will not be
     * called if a new surface is created, only if the valid surface has been replaced with another
     * valid surface.
     */
    private void notifySurfaceReplaced() {
        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
            mSurfaceChangedCallbacks.get(i).surfaceReplaced(mSurfaceChangedTransaction);
        }
    }

    private void notifySurfaceDestroyed() {
        for (int i = 0; i < mSurfaceChangedCallbacks.size(); i++) {
            mSurfaceChangedCallbacks.get(i).surfaceDestroyed();
        }
    }


    /**
     * Creates a surface as a child of {@code mSurface} with the same bounds as its parent and
     * crop bounds set to the parent's bounds adjusted for surface insets.
@@ -1984,7 +2033,7 @@ public final class ViewRootImpl implements ViewParent,
        mIsInTraversal = true;
        mWillDrawSoon = true;
        boolean windowSizeMayChange = false;
        boolean surfaceChanged = false;
        final boolean windowAttributesChanged = mWindowAttributesChanged;
        WindowManager.LayoutParams lp = mWindowAttributes;

        int desiredWindowWidth;
@@ -2003,7 +2052,6 @@ public final class ViewRootImpl implements ViewParent,
        WindowManager.LayoutParams params = null;
        if (mWindowAttributesChanged) {
            mWindowAttributesChanged = false;
            surfaceChanged = true;
            params = lp;
        }
        CompatibilityInfo compatibilityInfo =
@@ -2244,6 +2292,10 @@ public final class ViewRootImpl implements ViewParent,
        final boolean isViewVisible = viewVisibility == View.VISIBLE;
        final boolean windowRelayoutWasForced = mForceNextWindowRelayout;
        boolean surfaceSizeChanged = false;
        boolean surfaceCreated = false;
        boolean surfaceDestroyed = false;
        /* True if surface generation id changes. */
        boolean surfaceReplaced = false;

        if (mFirst || windowShouldResize || insetsChanged ||
                viewVisibilityChanged || params != null || mForceNextWindowRelayout) {
@@ -2325,10 +2377,14 @@ public final class ViewRootImpl implements ViewParent,
                final boolean outsetsChanged = !mPendingOutsets.equals(mAttachInfo.mOutsets);
                surfaceSizeChanged = (relayoutResult
                        & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0;
                surfaceChanged |= surfaceSizeChanged;
                final boolean alwaysConsumeSystemBarsChanged =
                        mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars;
                final boolean colorModeChanged = hasColorModeChanged(lp.getColorMode());
                surfaceCreated = !hadSurface && mSurface.isValid();
                surfaceDestroyed = hadSurface && !mSurface.isValid();
                surfaceReplaced = (surfaceGenerationId != mSurface.getGenerationId())
                        && mSurface.isValid();

                if (contentInsetsChanged) {
                    mAttachInfo.mContentInsets.set(mPendingContentInsets);
                    if (DEBUG_LAYOUT) Log.v(mTag, "Content insets changing to: "
@@ -2383,8 +2439,7 @@ public final class ViewRootImpl implements ViewParent,
                            lp.getColorMode() == ActivityInfo.COLOR_MODE_WIDE_COLOR_GAMUT);
                }

                if (!hadSurface) {
                    if (mSurface.isValid()) {
                if (surfaceCreated) {
                    // If we are creating a new surface, then we need to
                    // completely redraw it.
                    mFullRedrawNeeded = true;
@@ -2408,8 +2463,8 @@ public final class ViewRootImpl implements ViewParent,
                            return;
                        }
                    }
                    }
                } else if (!mSurface.isValid()) {
                    notifySurfaceCreated();
                } else if (surfaceDestroyed) {
                    // If the surface has been removed, then reset the scroll
                    // positions.
                    if (mLastScrolledFocus != null) {
@@ -2427,10 +2482,12 @@ public final class ViewRootImpl implements ViewParent,
                            mAttachInfo.mThreadedRenderer.isEnabled()) {
                        mAttachInfo.mThreadedRenderer.destroy();
                    }
                } else if ((surfaceGenerationId != mSurface.getGenerationId()
                    notifySurfaceDestroyed();
                } else if ((surfaceReplaced
                        || surfaceSizeChanged || windowRelayoutWasForced || colorModeChanged)
                        && mSurfaceHolder == null
                        && mAttachInfo.mThreadedRenderer != null) {
                        && mAttachInfo.mThreadedRenderer != null
                        && mSurface.isValid()) {
                    mFullRedrawNeeded = true;
                    try {
                        // Need to do updateSurface (which leads to CanvasContext::setSurface and
@@ -2448,6 +2505,10 @@ public final class ViewRootImpl implements ViewParent,
                    }
                }

                if (!surfaceCreated && surfaceReplaced) {
                    notifySurfaceReplaced();
                }

                final boolean freeformResizing = (relayoutResult
                        & WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM) != 0;
                final boolean dockedResizing = (relayoutResult
@@ -2503,31 +2564,32 @@ public final class ViewRootImpl implements ViewParent,
                }
                mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
                mSurfaceHolder.mSurfaceLock.unlock();
                if (mSurface.isValid()) {
                    if (!hadSurface) {
                if (surfaceCreated) {
                    mSurfaceHolder.ungetCallbacks();

                    mIsCreating = true;
                        SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
                    SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
                    if (callbacks != null) {
                        for (SurfaceHolder.Callback c : callbacks) {
                            c.surfaceCreated(mSurfaceHolder);
                        }
                    }
                        surfaceChanged = true;
                }
                    if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) {
                        SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();

                if ((surfaceCreated || surfaceReplaced || surfaceSizeChanged
                        || windowAttributesChanged) && mSurface.isValid()) {
                    SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
                    if (callbacks != null) {
                        for (SurfaceHolder.Callback c : callbacks) {
                            c.surfaceChanged(mSurfaceHolder, lp.format,
                                    mWidth, mHeight);
                        }
                    }
                    }
                    mIsCreating = false;
                } else if (hadSurface) {
                    notifySurfaceDestroyed();
                }

                if (surfaceDestroyed) {
                    notifyHolderSurfaceDestroyed();
                    mSurfaceHolder.mSurfaceLock.lock();
                    try {
                        mSurfaceHolder.mSurface = new Surface();
@@ -2841,7 +2903,7 @@ public final class ViewRootImpl implements ViewParent,
        }
    }

    private void notifySurfaceDestroyed() {
    private void notifyHolderSurfaceDestroyed() {
        mSurfaceHolder.ungetCallbacks();
        SurfaceHolder.Callback[] callbacks = mSurfaceHolder.getCallbacks();
        if (callbacks != null) {
@@ -3447,7 +3509,7 @@ public final class ViewRootImpl implements ViewParent,
    private void reportDrawFinished() {
        try {
            mDrawsNeededToReport = 0;
            mWindowSession.finishDrawing(mWindow, null /* postDrawTransaction */);
            mWindowSession.finishDrawing(mWindow, mSurfaceChangedTransaction);
        } catch (RemoteException e) {
            // Have fun!
        }