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

Commit e8f76a36 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

Merge "Reparent DisplayContent layers to SurfaceControl for ActivityView"

parents 299a573c ff2e7d8f
Loading
Loading
Loading
Loading
+39 −13
Original line number Original line Diff line number Diff line
@@ -34,7 +34,9 @@ import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEvent;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
import android.view.SurfaceView;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.WindowManager;
@@ -59,12 +61,16 @@ public class ActivityView extends ViewGroup {


    private VirtualDisplay mVirtualDisplay;
    private VirtualDisplay mVirtualDisplay;
    private final SurfaceView mSurfaceView;
    private final SurfaceView mSurfaceView;
    private Surface mSurface;

    /**
     * This is the root surface for the VirtualDisplay. The VirtualDisplay child surfaces will be
     * re-parented to this surface. This will also be a child of the SurfaceView's SurfaceControl.
     */
    private SurfaceControl mRootSurfaceControl;


    private final SurfaceCallback mSurfaceCallback;
    private final SurfaceCallback mSurfaceCallback;
    private StateCallback mActivityViewCallback;
    private StateCallback mActivityViewCallback;


    private IActivityManager mActivityManager;
    private IActivityTaskManager mActivityTaskManager;
    private IActivityTaskManager mActivityTaskManager;
    private IInputForwarder mInputForwarder;
    private IInputForwarder mInputForwarder;
    // Temp container to store view coordinates on screen.
    // Temp container to store view coordinates on screen.
@@ -75,6 +81,9 @@ public class ActivityView extends ViewGroup {
    private final CloseGuard mGuard = CloseGuard.get();
    private final CloseGuard mGuard = CloseGuard.get();
    private boolean mOpened; // Protected by mGuard.
    private boolean mOpened; // Protected by mGuard.


    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
    private Surface mTmpSurface = new Surface();

    @UnsupportedAppUsage
    @UnsupportedAppUsage
    public ActivityView(Context context) {
    public ActivityView(Context context) {
        this(context, null /* attrs */);
        this(context, null /* attrs */);
@@ -87,7 +96,6 @@ public class ActivityView extends ViewGroup {
    public ActivityView(Context context, AttributeSet attrs, int defStyle) {
    public ActivityView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        super(context, attrs, defStyle);


        mActivityManager = ActivityManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
        mActivityTaskManager = ActivityTaskManager.getService();
        mSurfaceView = new SurfaceView(context);
        mSurfaceView = new SurfaceView(context);
        mSurfaceCallback = new SurfaceCallback();
        mSurfaceCallback = new SurfaceCallback();
@@ -297,14 +305,19 @@ public class ActivityView extends ViewGroup {
    private class SurfaceCallback implements SurfaceHolder.Callback {
    private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            mSurface = mSurfaceView.getHolder().getSurface();
            mTmpSurface = new Surface();
            if (mVirtualDisplay == null) {
            if (mVirtualDisplay == null) {
                initVirtualDisplay();
                initVirtualDisplay(new SurfaceSession(surfaceHolder.getSurface()));
                if (mVirtualDisplay != null && mActivityViewCallback != null) {
                if (mVirtualDisplay != null && mActivityViewCallback != null) {
                    mActivityViewCallback.onActivityViewReady(ActivityView.this);
                    mActivityViewCallback.onActivityViewReady(ActivityView.this);
                }
                }
            } else {
            } else {
                mVirtualDisplay.setSurface(surfaceHolder.getSurface());
                // TODO (b/119209373): DisplayManager determines if a VirtualDisplay is on by
                // whether it has a surface. Setting a fake surface here so DisplayManager will
                // consider this display on.
                mVirtualDisplay.setSurface(mTmpSurface);
                mTmpTransaction.reparent(mRootSurfaceControl,
                        mSurfaceView.getSurfaceControl().getHandle()).apply();
            }
            }
            updateLocation();
            updateLocation();
        }
        }
@@ -319,8 +332,8 @@ public class ActivityView extends ViewGroup {


        @Override
        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            mSurface.release();
            mTmpSurface.release();
            mSurface = null;
            mTmpSurface = null;
            if (mVirtualDisplay != null) {
            if (mVirtualDisplay != null) {
                mVirtualDisplay.setSurface(null);
                mVirtualDisplay.setSurface(null);
            }
            }
@@ -328,7 +341,7 @@ public class ActivityView extends ViewGroup {
        }
        }
    }
    }


    private void initVirtualDisplay() {
    private void initVirtualDisplay(SurfaceSession surfaceSession) {
        if (mVirtualDisplay != null) {
        if (mVirtualDisplay != null) {
            throw new IllegalStateException("Trying to initialize for the second time.");
            throw new IllegalStateException("Trying to initialize for the second time.");
        }
        }
@@ -336,9 +349,13 @@ public class ActivityView extends ViewGroup {
        final int width = mSurfaceView.getWidth();
        final int width = mSurfaceView.getWidth();
        final int height = mSurfaceView.getHeight();
        final int height = mSurfaceView.getHeight();
        final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
        final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);

        // TODO (b/119209373): DisplayManager determines if a VirtualDisplay is on by
        // whether it has a surface. Setting a fake surface here so DisplayManager will consider
        // this display on.
        mVirtualDisplay = displayManager.createVirtualDisplay(
        mVirtualDisplay = displayManager.createVirtualDisplay(
                DISPLAY_NAME + "@" + System.identityHashCode(this),
                DISPLAY_NAME + "@" + System.identityHashCode(this),
                width, height, getBaseDisplayDensity(), mSurface,
                width, height, getBaseDisplayDensity(), mTmpSurface,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
                        | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
                        | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
        if (mVirtualDisplay == null) {
        if (mVirtualDisplay == null) {
@@ -348,11 +365,20 @@ public class ActivityView extends ViewGroup {


        final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
        final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
        final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
        final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();

        mRootSurfaceControl = new SurfaceControl.Builder(surfaceSession)
                .setContainerLayer(true)
                .setName(DISPLAY_NAME)
                .build();

        try {
        try {
            wm.reparentDisplayContent(displayId, mRootSurfaceControl.getHandle());
            wm.dontOverrideDisplayInfo(displayId);
            wm.dontOverrideDisplayInfo(displayId);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
            e.rethrowAsRuntimeException();
        }
        }

        mTmpTransaction.show(mRootSurfaceControl).apply();
        mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
        mInputForwarder = InputManager.getInstance().createInputForwarder(displayId);
        mTaskStackListener = new TaskStackListenerImpl();
        mTaskStackListener = new TaskStackListenerImpl();
        try {
        try {
@@ -392,9 +418,9 @@ public class ActivityView extends ViewGroup {
            displayReleased = false;
            displayReleased = false;
        }
        }


        if (mSurface != null) {
        if (mTmpSurface != null) {
            mSurface.release();
            mTmpSurface.release();
            mSurface = null;
            mTmpSurface = null;
        }
        }


        if (displayReleased && mActivityViewCallback != null) {
        if (displayReleased && mActivityViewCallback != null) {
+12 −0
Original line number Original line Diff line number Diff line
@@ -551,4 +551,16 @@ interface IWindowManager
     * @see KeyguardManager#isDeviceLocked()
     * @see KeyguardManager#isDeviceLocked()
     */
     */
    void setShouldShowIme(int displayId, boolean shouldShow);
    void setShouldShowIme(int displayId, boolean shouldShow);

     /**
     * Reparent the top layers for a display to the requested surfaceControl. The display that
     * is going to be re-parented (the displayId passed in) needs to have been created by the same
     * process that is requesting the re-parent. This is to ensure clients can't just re-parent
     * display content info to any SurfaceControl, as this would be a security issue.
     *
     * @param displayId The id of the display.
     * @param surfaceControlHandle The SurfaceControl handle that the top level layers for the
     *        display should be re-parented to.
     */
    void reparentDisplayContent(int displayId, in IBinder surfaceControlHandle);
}
}
+7 −0
Original line number Original line Diff line number Diff line
@@ -1126,6 +1126,13 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
        }
        }
    };
    };


    /**
     * @hide
     */
    public SurfaceControl getSurfaceControl() {
        return mSurfaceControl;
    }

    class SurfaceControlWithBackground extends SurfaceControl {
    class SurfaceControlWithBackground extends SurfaceControl {
        SurfaceControl mBackgroundControl;
        SurfaceControl mBackgroundControl;
        private boolean mOpaque = true;
        private boolean mOpaque = true;
+13 −1
Original line number Original line Diff line number Diff line
@@ -29,12 +29,12 @@ import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.InsetsState.TYPE_IME;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
import static android.view.View.GONE;
import static android.view.InsetsState.TYPE_IME;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
import static android.view.WindowManager.DOCKED_TOP;
@@ -4736,4 +4736,16 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                || mDisplayId == mWmService.mVr2dDisplayId
                || mDisplayId == mWmService.mVr2dDisplayId
                || mWmService.mForceDesktopModeOnExternalDisplays;
                || mWmService.mForceDesktopModeOnExternalDisplays;
    }
    }

     /**
     * Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
     * {@link #mOverlayLayer} to the specified surfaceControl.
     *
     * @param surfaceControlHandle The handle for the new SurfaceControl, where the DisplayContent's
     *                             surfaces will be re-parented to.
     */
    void reparentDisplayContent(IBinder surfaceControlHandle) {
        mPendingTransaction.reparent(mWindowingLayer, surfaceControlHandle)
                .reparent(mOverlayLayer, surfaceControlHandle);
    }
}
}
+25 −0
Original line number Original line Diff line number Diff line
@@ -7448,4 +7448,29 @@ public class WindowManagerService extends IWindowManager.Stub
            }
            }
        }
        }
    }
    }

    @Override
    public void reparentDisplayContent(int displayId, IBinder surfaceControlHandle) {
        final Display display = mDisplayManager.getDisplay(displayId);
        if (display == null) {
            throw new IllegalArgumentException(
                    "Can't reparent display for non-existent displayId: " + displayId);
        }

        final int callingUid = Binder.getCallingUid();
        final int displayOwnerUid = display.getOwnerUid();
        if (callingUid != displayOwnerUid) {
            throw new SecurityException("Only owner of the display can reparent surfaces to it.");
        }

        synchronized (mGlobalLock) {
            long token = Binder.clearCallingIdentity();
            try {
                DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
                displayContent.reparentDisplayContent(surfaceControlHandle);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }
    }
}
}