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

Commit 449e06df authored by Robert Carr's avatar Robert Carr Committed by Rob Carr
Browse files

SurfaceControlViewHost: Basic child window support

WindowlessWindowManager already has some support for multiple
windows so the main thing we need to do is just ensure that the
Windowless session is injected in to the ViewRoot of things attached
to our token. We can do this via some somewhat unsightly glue
code in WindowManagerGlobal.

Bug: 218615203
Test: SurfaceControlViewHostTests
Change-Id: Icce97c02b6155a7ef368821670db26728b95b6b9
parent d39c2182
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -27,8 +27,10 @@ import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.util.Log;
import android.view.accessibility.IAccessibilityEmbeddedConnection;
import android.view.InsetsState;
import android.view.WindowManagerGlobal;

import java.util.Objects;

@@ -43,11 +45,13 @@ import java.util.Objects;
 * {@link SurfaceView#setChildSurfacePackage}.
 */
public class SurfaceControlViewHost {
    private final static String TAG = "SurfaceControlViewHost";
    private final ViewRootImpl mViewRoot;
    private WindowlessWindowManager mWm;

    private SurfaceControl mSurfaceControl;
    private IAccessibilityEmbeddedConnection mAccessibilityEmbeddedConnection;
    private boolean mReleased = false;

    private final class ISurfaceControlViewHostImpl extends ISurfaceControlViewHost.Stub {
        @Override
@@ -268,6 +272,8 @@ public class SurfaceControlViewHost {
            @NonNull WindowlessWindowManager wwm, boolean useSfChoreographer) {
        mWm = wwm;
        mViewRoot = new ViewRootImpl(c, d, mWm, useSfChoreographer);
        WindowManagerGlobal.getInstance().addWindowlessRoot(mViewRoot);

        mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
    }

@@ -292,7 +298,10 @@ public class SurfaceControlViewHost {
                .build();
        mWm = new WindowlessWindowManager(context.getResources().getConfiguration(),
                mSurfaceControl, hostToken);

        mViewRoot = new ViewRootImpl(context, display, mWm);
        WindowManagerGlobal.getInstance().addWindowlessRoot(mViewRoot);

        mAccessibilityEmbeddedConnection = mViewRoot.getAccessibilityEmbeddedConnection();
    }

@@ -301,12 +310,15 @@ public class SurfaceControlViewHost {
     */
    @Override
    protected void finalize() throws Throwable {
        // We aren't on the UI thread here so we need to pass false to
        // doDie
        if (mReleased) {
            return;
        }
        Log.e(TAG, "SurfaceControlViewHost finalized without being released: " + this);
        // We aren't on the UI thread here so we need to pass false to doDie
        mViewRoot.die(false /* immediate */);
        WindowManagerGlobal.getInstance().removeWindowlessRoot(mViewRoot);
    }


    /**
     * Return a SurfacePackage for the root SurfaceControl of the embedded hierarchy.
     * Rather than be directly reparented using {@link SurfaceControl.Transaction} this
@@ -413,5 +425,7 @@ public class SurfaceControlViewHost {
    public void release() {
        // ViewRoot will release mSurfaceControl for us.
        mViewRoot.die(true /* immediate */);
        WindowManagerGlobal.getInstance().removeWindowlessRoot(mViewRoot);
        mReleased = true;
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -10851,4 +10851,8 @@ public final class ViewRootImpl implements ViewParent,
        mLastGivenInsets.reset();
        requestLayout();
    }

    IWindowSession getWindowSession() {
        return mWindowSession;
    }
}
+35 −1
Original line number Diff line number Diff line
@@ -159,6 +159,8 @@ public final class WindowManagerGlobal {
            new ArrayList<WindowManager.LayoutParams>();
    private final ArraySet<View> mDyingViews = new ArraySet<View>();

    private final ArrayList<ViewRootImpl> mWindowlessRoots = new ArrayList<ViewRootImpl>();

    private Runnable mSystemPropertyUpdater;

    private WindowManagerGlobal() {
@@ -387,7 +389,25 @@ public final class WindowManagerGlobal {
                }
            }

            IWindowSession windowlessSession = null;
            // If there is a parent set, but we can't find it, it may be coming
            // from a SurfaceControlViewHost hierarchy.
            if (wparams.token != null && panelParentView == null) {
                for (int i = 0; i < mWindowlessRoots.size(); i++) {
                    ViewRootImpl maybeParent = mWindowlessRoots.get(i);
                    if (maybeParent.getWindowToken() == wparams.token) {
                        windowlessSession = maybeParent.getWindowSession();
                        break;
                    }
                }
            }

            if (windowlessSession == null) {
                root = new ViewRootImpl(view.getContext(), display);
            } else {
                root = new ViewRootImpl(view.getContext(), display,
                        windowlessSession);
            }

            view.setLayoutParams(wparams);

@@ -720,6 +740,20 @@ public final class WindowManagerGlobal {
            throw e.rethrowFromSystemServer();
        }
    }

    /** @hide */
    public void addWindowlessRoot(ViewRootImpl impl) {
        synchronized (mLock) {
            mWindowlessRoots.add(impl);
        }
    }

    /** @hide */
    public void removeWindowlessRoot(ViewRootImpl impl) {
        synchronized (mLock) {
            mWindowlessRoots.remove(impl);
        }
    }
}

final class WindowLeaked extends AndroidRuntimeException {