diff options
3 files changed, 130 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index a11dd3b7f213..9427c270c57f 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -37,10 +37,12 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_S import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; +import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; import static android.hardware.display.DisplayManagerGlobal.DisplayEvent; import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL; @@ -1800,7 +1802,11 @@ public final class DisplayManagerService extends SystemService { } if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { - flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; + if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) == 0) { + Slog.d(TAG, "Public virtual displays are auto mirror by default, hence adding " + + "VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR."); + flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; + } // Public displays can't be allowed to show content when locked. if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { @@ -1808,10 +1814,16 @@ public final class DisplayManagerService extends SystemService { "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE"); } } - if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) { + if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { + Slog.d(TAG, "Own content displays cannot auto mirror other displays, hence ignoring " + + "VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR."); flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR; } - if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { + if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { + Slog.d(TAG, "Auto mirror displays must be in the default display group, hence ignoring " + + "VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP."); flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP; } // Put the display in the virtual device's display group only if it's not a mirror display, @@ -1821,6 +1833,8 @@ public final class DisplayManagerService extends SystemService { && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) == 0 && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == VIRTUAL_DISPLAY_FLAG_TRUSTED && virtualDevice != null) { + Slog.d(TAG, "Own content displays owned by virtual devices are put in that device's " + + "display group, hence adding VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP."); flags |= VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP; } @@ -1852,8 +1866,7 @@ public final class DisplayManagerService extends SystemService { Binder.restoreCallingIdentity(firstToken); } - if (callingUid != Process.SYSTEM_UID - && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { + if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) { // Only a valid media projection or a virtual device can create a mirror virtual // display. if (!canProjectVideo(projection) && !canCreateMirrorDisplays(virtualDevice) @@ -1901,6 +1914,14 @@ public final class DisplayManagerService extends SystemService { } } + if ((flags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) == 0 + && (flags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) == 0) { + Slog.d(TAG, "Always unlocked displays cannot be in the default display group, hence " + + "ignoring flag VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED."); + flags &= ~VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED; + } + if ((flags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) { if (callingUid != Process.SYSTEM_UID && !checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY, @@ -1911,7 +1932,24 @@ public final class DisplayManagerService extends SystemService { } } - if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { + if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { + Slog.d(TAG, "Untrusted displays cannot have own focus, hence ignoring flag " + + "VIRTUAL_DISPLAY_FLAG_OWN_FOCUS."); + flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_FOCUS; + } + + if ((flags & VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) == 0) { + Slog.d(TAG, "Virtual displays that cannot steal top focus must have their own " + + " focus, hence ignoring flag VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED."); + flags &= ~VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED; + } + + if ((flags & VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0 + && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) { + Slog.d(TAG, "Untrusted displays cannot show system decorations, hence ignoring flag " + + "VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS."); flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; } diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 558afd1da380..abbdeb9da364 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -33,13 +33,6 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPO import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED; import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; -import static com.android.server.display.DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED; -import static com.android.server.display.DisplayDeviceInfo.FLAG_DEVICE_DISPLAY_GROUP; -import static com.android.server.display.DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP; -import static com.android.server.display.DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED; -import static com.android.server.display.DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED; -import static com.android.server.display.DisplayDeviceInfo.FLAG_TRUSTED; - import android.annotation.Nullable; import android.content.Context; import android.graphics.Point; @@ -574,15 +567,13 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mInfo.flags &= ~DisplayDeviceInfo.FLAG_NEVER_BLANK; } else { mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY; - - if ((mFlags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { - mInfo.flags |= FLAG_OWN_DISPLAY_GROUP; - } + } + if ((mFlags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) { + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) { - mInfo.flags |= FLAG_DEVICE_DISPLAY_GROUP; + mInfo.flags |= DisplayDeviceInfo.FLAG_DEVICE_DISPLAY_GROUP; } - if ((mFlags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) { mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE; } @@ -611,41 +602,19 @@ public class VirtualDisplayAdapter extends DisplayAdapter { mInfo.flags |= DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { - mInfo.flags |= FLAG_TRUSTED; + mInfo.flags |= DisplayDeviceInfo.FLAG_TRUSTED; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED) != 0) { - if ((mInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0 - || (mFlags & VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP) != 0) { - mInfo.flags |= FLAG_ALWAYS_UNLOCKED; - } else { - Slog.w( - TAG, - "Ignoring VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED as it requires" - + " VIRTUAL_DISPLAY_FLAG_DEVICE_DISPLAY_GROUP or" - + " VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP."); - } + mInfo.flags |= DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { - mInfo.flags |= FLAG_TOUCH_FEEDBACK_DISABLED; + mInfo.flags |= DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) != 0) { - if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) { - mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_FOCUS; - } else { - Slog.w(TAG, "Ignoring VIRTUAL_DISPLAY_FLAG_OWN_FOCUS as it requires " - + "VIRTUAL_DISPLAY_FLAG_TRUSTED."); - } + mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_FOCUS; } if ((mFlags & VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED) != 0) { - if ((mFlags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0 - && (mFlags & VIRTUAL_DISPLAY_FLAG_OWN_FOCUS) != 0) { - mInfo.flags |= FLAG_STEAL_TOP_FOCUS_DISABLED; - } else { - Slog.w(TAG, - "Ignoring VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED as it " - + "requires VIRTUAL_DISPLAY_FLAG_OWN_FOCUS which requires " - + "VIRTUAL_DISPLAY_FLAG_TRUSTED."); - } + mInfo.flags |= DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED; } mInfo.type = Display.TYPE_VIRTUAL; diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java index b5ea0df98204..72f08dd07658 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java @@ -759,6 +759,83 @@ public class DisplayManagerServiceTest { } @Test + public void testCreateVirtualDisplayStealTopFocusDisabled() throws RemoteException { + DisplayManagerService displayManager = + new DisplayManagerService(mContext, mBasicInjector); + registerDefaultDisplays(displayManager); + + // This is effectively the DisplayManager service published to ServiceManager. + DisplayManagerService.BinderService bs = displayManager.new BinderService(); + + String uniqueId = "uniqueId --- Steal Top Focus Test"; + int width = 600; + int height = 800; + int dpi = 320; + int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED + | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS + | DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; + + when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn( + PackageManager.PERMISSION_GRANTED); + when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); + final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder( + VIRTUAL_DISPLAY_NAME, width, height, dpi); + builder.setFlags(flags); + builder.setUniqueId(uniqueId); + int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken, + /* projection= */ null, PACKAGE_NAME); + verify(mMockProjectionService, never()).setContentRecordingSession(any(), + nullable(IMediaProjection.class)); + + performTraversalInternal(displayManager); + + // flush the handler + displayManager.getDisplayHandler().runWithScissors(() -> {}, /* now= */ 0); + + DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); + assertNotNull(ddi); + assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED) != 0); + } + + @Test + public void testCreateVirtualDisplayOwnFocus_nonOwnFocusDisplay() throws RemoteException { + DisplayManagerService displayManager = + new DisplayManagerService(mContext, mBasicInjector); + registerDefaultDisplays(displayManager); + + // This is effectively the DisplayManager service published to ServiceManager. + DisplayManagerService.BinderService bs = displayManager.new BinderService(); + + String uniqueId = "uniqueId --- Steal Top Focus Test -- nonOwnFocusDisplay"; + int width = 600; + int height = 800; + int dpi = 320; + int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_STEAL_TOP_FOCUS_DISABLED + | DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED; + + when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn( + PackageManager.PERMISSION_GRANTED); + when(mMockAppToken.asBinder()).thenReturn(mMockAppToken); + final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder( + VIRTUAL_DISPLAY_NAME, width, height, dpi); + builder.setFlags(flags); + builder.setUniqueId(uniqueId); + int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken, + /* projection= */ null, PACKAGE_NAME); + verify(mMockProjectionService, never()).setContentRecordingSession(any(), + nullable(IMediaProjection.class)); + + performTraversalInternal(displayManager); + + // flush the handler + displayManager.getDisplayHandler().runWithScissors(() -> {}, /* now= */ 0); + + DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId); + assertNotNull(ddi); + assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED) == 0); + } + + @Test public void testCreateVirtualDisplayOwnFocus_checkDisplayDeviceInfo() throws RemoteException { DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector); |