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

Commit da4c694b authored by chaviw's avatar chaviw
Browse files

Added turn on/off virtual display

VirtualDisplays are considered on if they have a surface and off if they don't.
This causes problems for displays that don't have a surface. Instead,
create a separate API to allow the client to request the surface be on
or off.

To ensure backwards compatibility for VirtualDisplays, set the display
to on or off when the surface is added or removed.

Change-Id: If9d8db94a66d6484ac492a53c1cd8fb7da851b88
Fixes: 119209373
Test: Created surfaceless virtual display that can be manually turned on or off
parent 36d3b7a0
Loading
Loading
Loading
Loading
+14 −23
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package android.app;

import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;

import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager.StackInfo;
@@ -32,7 +36,6 @@ import android.util.Log;
import android.view.IWindowManager;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
@@ -81,7 +84,6 @@ public class ActivityView extends ViewGroup {
    private boolean mOpened; // Protected by mGuard.

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

    @UnsupportedAppUsage
    public ActivityView(Context context) {
@@ -309,20 +311,20 @@ public class ActivityView extends ViewGroup {
    private class SurfaceCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
            mTmpSurface = new Surface();
            if (mVirtualDisplay == null) {
                initVirtualDisplay(new SurfaceSession(surfaceHolder.getSurface()));
                if (mVirtualDisplay != null && mActivityViewCallback != null) {
                    mActivityViewCallback.onActivityViewReady(ActivityView.this);
                }
            } else {
                // 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();
            }

            if (mVirtualDisplay != null) {
                mVirtualDisplay.setDisplayState(true);
            }

            updateLocation();
        }

@@ -336,10 +338,8 @@ public class ActivityView extends ViewGroup {

        @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            mTmpSurface.release();
            mTmpSurface = null;
            if (mVirtualDisplay != null) {
                mVirtualDisplay.setSurface(null);
                mVirtualDisplay.setDisplayState(false);
            }
            cleanTapExcludeRegion();
        }
@@ -354,15 +354,11 @@ public class ActivityView extends ViewGroup {
        final int height = mSurfaceView.getHeight();
        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(
                DISPLAY_NAME + "@" + System.identityHashCode(this),
                width, height, getBaseDisplayDensity(), mTmpSurface,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC
                        | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
                        | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
                DISPLAY_NAME + "@" + System.identityHashCode(this), width, height,
                getBaseDisplayDensity(), null,
                VIRTUAL_DISPLAY_FLAG_PUBLIC | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY
                        | VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL);
        if (mVirtualDisplay == null) {
            Log.e(TAG, "Failed to initialize ActivityView");
            return;
@@ -423,11 +419,6 @@ public class ActivityView extends ViewGroup {
            displayReleased = false;
        }

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

        if (displayReleased && mActivityViewCallback != null) {
            mActivityViewCallback.onActivityViewDestroyed(this);
        }
+9 −0
Original line number Diff line number Diff line
@@ -447,6 +447,7 @@ public final class DisplayManagerGlobal {
    public void setVirtualDisplaySurface(IVirtualDisplayCallback token, Surface surface) {
        try {
            mDm.setVirtualDisplaySurface(token, surface);
            setVirtualDisplayState(token, surface != null);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
@@ -469,6 +470,14 @@ public final class DisplayManagerGlobal {
        }
    }

    void setVirtualDisplayState(IVirtualDisplayCallback token, boolean isOn) {
        try {
            mDm.setVirtualDisplayState(token, isOn);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the stable device display size, in pixels.
     */
+3 −0
Original line number Diff line number Diff line
@@ -85,6 +85,9 @@ interface IDisplayManager {
    // No permissions required but must be same Uid as the creator.
    void releaseVirtualDisplay(in IVirtualDisplayCallback token);

    // No permissions required but must be same Uid as the creator.
    void setVirtualDisplayState(in IVirtualDisplayCallback token, boolean isOn);

    // Get a stable metric for the device's display size. No permissions required.
    Point getStableDisplaySize();

+12 −0
Original line number Diff line number Diff line
@@ -104,6 +104,18 @@ public final class VirtualDisplay {
        }
    }

    /**
     * Sets the on/off state for a virtual display.
     *
     * @param isOn Whether the display should be on or off.
     * @hide
     */
    public void setDisplayState(boolean isOn) {
        if (mToken != null) {
            mGlobal.setVirtualDisplayState(mToken, isOn);
        }
    }

    @Override
    public String toString() {
        return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken
+20 −0
Original line number Diff line number Diff line
@@ -812,6 +812,16 @@ public final class DisplayManagerService extends SystemService {
        }
    }

    private void setVirtualDisplayStateInternal(IBinder appToken, boolean isOn) {
        synchronized (mSyncRoot) {
            if (mVirtualDisplayAdapter == null) {
                return;
            }

            mVirtualDisplayAdapter.setVirtualDisplayStateLocked(appToken, isOn);
        }
    }

    private void registerDefaultDisplayAdapters() {
        // Register default display adapters.
        synchronized (mSyncRoot) {
@@ -1955,6 +1965,16 @@ public final class DisplayManagerService extends SystemService {
            }
        }

        @Override // Binder call
        public void setVirtualDisplayState(IVirtualDisplayCallback callback, boolean isOn) {
            final long token = Binder.clearCallingIdentity();
            try {
                setVirtualDisplayStateInternal(callback.asBinder(), isOn);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override // Binder call
        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Loading