From 8085fe75d18b753b74f1388909b1d22b727f79e6 Mon Sep 17 00:00:00 2001 From: Victor Chang Date: Mon, 1 Mar 2021 13:21:54 +0000 Subject: [PATCH] Revert "Clean up LogicalDisplayMapper" Revert submission 13575048-clean_ldm Reason for revert: http://b/181537022 Reverted Changes: I69c3478b4:Adjust jumbojack config to fit latest display layo... I72a4eb667:Clean up LogicalDisplayMapper Change-Id: I392816dd3870bd1ab969c06e796977a9d39bafda --- core/java/android/view/DisplayInfo.java | 3 - core/res/res/values/config.xml | 9 - core/res/res/values/symbols.xml | 1 - .../display/DeviceStateToLayoutMap.java | 32 +- .../android/server/display/DisplayGroup.java | 15 +- .../server/display/DisplayManagerService.java | 56 +- .../server/display/LogicalDisplay.java | 42 +- .../server/display/LogicalDisplayMapper.java | 541 +++++++----------- .../display/LogicalDisplayMapperTest.java | 328 ----------- 9 files changed, 253 insertions(+), 774 deletions(-) delete mode 100644 services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java index 655f42308a1f..2a00b5a2e513 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -810,9 +810,6 @@ public final class DisplayInfo implements Parcelable { if ((flags & Display.FLAG_TRUSTED) != 0) { result.append(", FLAG_TRUSTED"); } - if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) { - result.append(", FLAG_OWN_DISPLAY_GROUP"); - } return result.toString(); } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 10164b0d2b1c..12cb3980f785 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -673,15 +673,6 @@ --> - - - - - diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 8f07a2d49ce6..dbb584dfe293 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3762,7 +3762,6 @@ - diff --git a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java index 91674cd8afa6..d4556ed5f9fa 100644 --- a/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java +++ b/services/core/java/com/android/server/display/DeviceStateToLayoutMap.java @@ -39,6 +39,10 @@ class DeviceStateToLayoutMap { public static final int STATE_DEFAULT = DeviceStateManager.INVALID_DEVICE_STATE; + // TODO - b/168208162 - Remove these when we check in static definitions for layouts + public static final int STATE_FOLDED = 100; + public static final int STATE_UNFOLDED = 101; + private final SparseArray mLayoutMap = new SparseArray<>(); DeviceStateToLayoutMap(Context context) { @@ -64,7 +68,7 @@ class DeviceStateToLayoutMap { return layout; } - private Layout createLayout(int state) { + private Layout create(int state) { if (mLayoutMap.contains(state)) { Slog.e(TAG, "Attempted to create a second layout for state " + state); return null; @@ -75,12 +79,10 @@ class DeviceStateToLayoutMap { return layout; } - /** - * Loads config.xml-specified folded configurations for foldable devices. - */ private void loadFoldedDisplayConfig(Context context) { final String[] strDisplayIds = context.getResources().getStringArray( com.android.internal.R.array.config_internalFoldedPhysicalDisplayIds); + if (strDisplayIds.length != 2 || TextUtils.isEmpty(strDisplayIds[0]) || TextUtils.isEmpty(strDisplayIds[1])) { Slog.w(TAG, "Folded display configuration invalid: [" + Arrays.toString(strDisplayIds) @@ -101,23 +103,19 @@ class DeviceStateToLayoutMap { final int[] foldedDeviceStates = context.getResources().getIntArray( com.android.internal.R.array.config_foldedDeviceStates); - final int[] unfoldedDeviceStates = context.getResources().getIntArray( - com.android.internal.R.array.config_unfoldedDeviceStates); // Only add folded states if folded state config is not empty - if (foldedDeviceStates.length == 0 || unfoldedDeviceStates.length == 0) { + if (foldedDeviceStates.length == 0) { return; } - for (int state : foldedDeviceStates) { - // Create the folded state layout - createLayout(state).createDisplayLocked( - DisplayAddress.fromPhysicalDisplayId(displayIds[0]), true /*isDefault*/); - } + // Create the folded state layout + final Layout foldedLayout = create(STATE_FOLDED); + foldedLayout.createDisplayLocked( + DisplayAddress.fromPhysicalDisplayId(displayIds[0]), true /*isDefault*/); - for (int state : unfoldedDeviceStates) { - // Create the unfolded state layout - createLayout(state).createDisplayLocked( - DisplayAddress.fromPhysicalDisplayId(displayIds[1]), true /*isDefault*/); - } + // Create the unfolded state layout + final Layout unfoldedLayout = create(STATE_UNFOLDED); + unfoldedLayout.createDisplayLocked( + DisplayAddress.fromPhysicalDisplayId(displayIds[1]), true /*isDefault*/); } } diff --git a/services/core/java/com/android/server/display/DisplayGroup.java b/services/core/java/com/android/server/display/DisplayGroup.java index 2dcd5ccaf557..663883ab2825 100644 --- a/services/core/java/com/android/server/display/DisplayGroup.java +++ b/services/core/java/com/android/server/display/DisplayGroup.java @@ -30,8 +30,6 @@ public class DisplayGroup { private final List mDisplays = new ArrayList<>(); private final int mGroupId; - private int mChangeCount; - DisplayGroup(int groupId) { mGroupId = groupId; } @@ -47,16 +45,11 @@ public class DisplayGroup { * @param display the {@link LogicalDisplay} to add to the Group */ void addDisplayLocked(LogicalDisplay display) { - if (!containsLocked(display)) { - mChangeCount++; + if (!mDisplays.contains(display)) { mDisplays.add(display); } } - boolean containsLocked(LogicalDisplay display) { - return mDisplays.contains(display); - } - /** * Removes the provided {@code display} from the Group. * @@ -64,7 +57,6 @@ public class DisplayGroup { * @return {@code true} if the {@code display} was removed; otherwise {@code false} */ boolean removeDisplayLocked(LogicalDisplay display) { - mChangeCount++; return mDisplays.remove(display); } @@ -73,11 +65,6 @@ public class DisplayGroup { return mDisplays.isEmpty(); } - /** Returns a count of the changes made to this display group. */ - int getChangeCountLocked() { - return mChangeCount; - } - /** Returns the number of {@link LogicalDisplay LogicalDisplays} in the Group. */ int getSizeLocked() { return mDisplays.size(); diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 6fc3e09bed0b..c62dd72ada70 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -485,13 +485,13 @@ public final class DisplayManagerService extends SystemService { synchronized (mSyncRoot) { long timeout = SystemClock.uptimeMillis() + mInjector.getDefaultDisplayDelayTimeout(); - while (mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) == null + while (mLogicalDisplayMapper.getLocked(Display.DEFAULT_DISPLAY) == null || mVirtualDisplayAdapter == null) { long delay = timeout - SystemClock.uptimeMillis(); if (delay <= 0) { throw new RuntimeException("Timeout waiting for default display " + "to be initialized. DefaultDisplay=" - + mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY) + + mLogicalDisplayMapper.getLocked(Display.DEFAULT_DISPLAY) + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter); } if (DEBUG) { @@ -549,7 +549,7 @@ public final class DisplayManagerService extends SystemService { mSystemReady = true; // Just in case the top inset changed before the system was ready. At this point, any // relevant configuration should be in place. - recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)); + recordTopInsetLocked(mLogicalDisplayMapper.getLocked(Display.DEFAULT_DISPLAY)); updateSettingsLocked(); } @@ -617,7 +617,7 @@ public final class DisplayManagerService extends SystemService { @VisibleForTesting void setDisplayInfoOverrideFromWindowManagerInternal(int displayId, DisplayInfo info) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { if (display.setDisplayInfoOverrideFromWindowManagerLocked(info)) { handleLogicalDisplayChangedLocked(display); @@ -632,7 +632,7 @@ public final class DisplayManagerService extends SystemService { */ private void getNonOverrideDisplayInfoInternal(int displayId, DisplayInfo outInfo) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + final LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { display.getNonOverrideDisplayInfoLocked(outInfo); } @@ -691,8 +691,8 @@ public final class DisplayManagerService extends SystemService { mDisplayStates.setValueAt(index, state); mDisplayBrightnesses.setValueAt(index, brightnessState); - runnable = updateDisplayStateLocked(mLogicalDisplayMapper.getDisplayLocked(displayId) - .getPrimaryDisplayDeviceLocked()); + runnable = updateDisplayStateLocked( + mLogicalDisplayMapper.getLocked(displayId).getPrimaryDisplayDeviceLocked()); } // Setting the display power state can take hundreds of milliseconds @@ -803,9 +803,9 @@ public final class DisplayManagerService extends SystemService { private DisplayInfo getDisplayInfoInternal(int displayId, int callingUid) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { - final DisplayInfo info = + DisplayInfo info = getDisplayInfoForFrameRateOverride(display.getFrameRateOverrides(), display.getDisplayInfoLocked(), callingUid); if (info.hasAccess(callingUid) @@ -952,7 +952,7 @@ public final class DisplayManagerService extends SystemService { private void requestColorModeInternal(int displayId, int colorMode) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null && display.getRequestedColorModeLocked() != colorMode) { display.setRequestedColorModeLocked(colorMode); @@ -989,7 +989,7 @@ public final class DisplayManagerService extends SystemService { mDisplayDeviceRepo.onDisplayDeviceEvent(device, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED); - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(device); if (display != null) { return display.getDisplayIdLocked(); } @@ -1203,7 +1203,7 @@ public final class DisplayManagerService extends SystemService { // TODO - b/170498827 The rules regarding what display state to apply to each // display will depend on the configuration/mapping of logical displays. // Clean up LogicalDisplay.isEnabled() mechanism once this is fixed. - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); + final LogicalDisplay display = mLogicalDisplayMapper.getLocked(device); final int state; final int displayId = display.getDisplayIdLocked(); @@ -1364,7 +1364,7 @@ public final class DisplayManagerService extends SystemService { float requestedRefreshRate, int requestedModeId, boolean preferMinimalPostProcessing, boolean inTraversal) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display == null) { return; } @@ -1406,7 +1406,7 @@ public final class DisplayManagerService extends SystemService { private void setDisplayOffsetsInternal(int displayId, int x, int y) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display == null) { return; } @@ -1424,7 +1424,7 @@ public final class DisplayManagerService extends SystemService { private void setDisplayScalingDisabledInternal(int displayId, boolean disable) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + final LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display == null) { return; } @@ -1460,7 +1460,7 @@ public final class DisplayManagerService extends SystemService { @Nullable private IBinder getDisplayToken(int displayId) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + final LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { final DisplayDevice device = display.getPrimaryDisplayDeviceLocked(); if (device != null) { @@ -1478,7 +1478,7 @@ public final class DisplayManagerService extends SystemService { if (token == null) { return null; } - final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayId); + final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getLocked(displayId); if (logicalDisplay == null) { return null; } @@ -1611,16 +1611,15 @@ public final class DisplayManagerService extends SystemService { // Find the logical display that the display device is showing. // Certain displays only ever show their own content. - LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(device); if (!ownContent) { if (display != null && !display.hasContentLocked()) { // If the display does not have any content of its own, then // automatically mirror the requested logical display contents if possible. - display = mLogicalDisplayMapper.getDisplayLocked( - device.getDisplayIdToMirrorLocked()); + display = mLogicalDisplayMapper.getLocked(device.getDisplayIdToMirrorLocked()); } if (display == null) { - display = mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY); + display = mLogicalDisplayMapper.getLocked(Display.DEFAULT_DISPLAY); } } @@ -1897,9 +1896,9 @@ public final class DisplayManagerService extends SystemService { @VisibleForTesting DisplayDeviceInfo getDisplayDeviceInfoInternal(int displayId) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { - final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); + DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); return displayDevice.getDisplayDeviceInfoLocked(); } return null; @@ -1909,9 +1908,9 @@ public final class DisplayManagerService extends SystemService { @VisibleForTesting int getDisplayIdToMirrorInternal(int displayId) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { - final DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); + DisplayDevice displayDevice = display.getPrimaryDisplayDeviceLocked(); return displayDevice.getDisplayIdToMirrorLocked(); } return Display.INVALID_DISPLAY; @@ -1993,8 +1992,7 @@ public final class DisplayManagerService extends SystemService { ArraySet uids; synchronized (mSyncRoot) { int displayId = msg.arg1; - final LogicalDisplay display = - mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); uids = display.getPendingFrameRateOverrideUids(); display.clearPendingFrameRateOverrideUids(); } @@ -2588,7 +2586,7 @@ public final class DisplayManagerService extends SystemService { @Override // Binder call public boolean isMinimalPostProcessingRequested(int displayId) { synchronized (mSyncRoot) { - return mLogicalDisplayMapper.getDisplayLocked(displayId) + return mLogicalDisplayMapper.getLocked(displayId) .getRequestedMinimalPostProcessingLocked(); } } @@ -2833,7 +2831,7 @@ public final class DisplayManagerService extends SystemService { @Override public Point getDisplayPosition(int displayId) { synchronized (mSyncRoot) { - final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId); + LogicalDisplay display = mLogicalDisplayMapper.getLocked(displayId); if (display != null) { return display.getDisplayPosition(); } diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java index d9570c710b15..20b133ce4d0a 100644 --- a/services/core/java/com/android/server/display/LogicalDisplay.java +++ b/services/core/java/com/android/server/display/LogicalDisplay.java @@ -17,11 +17,11 @@ package com.android.server.display; import android.annotation.NonNull; -import android.annotation.Nullable; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManagerInternal; import android.util.ArraySet; +import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayEventReceiver; @@ -64,14 +64,12 @@ import java.util.Objects; */ final class LogicalDisplay { private static final String TAG = "LogicalDisplay"; + private final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); // The layer stack we use when the display has been blanked to prevent any // of its content from appearing. private static final int BLANK_LAYER_STACK = -1; - private static final DisplayInfo EMPTY_DISPLAY_INFO = new DisplayInfo(); - - private final DisplayInfo mBaseDisplayInfo = new DisplayInfo(); private final int mDisplayId; private final int mLayerStack; @@ -299,7 +297,7 @@ final class LogicalDisplay { // Check whether logical display has become invalid. if (!deviceRepo.containsLocked(mPrimaryDisplayDevice)) { - setPrimaryDisplayDeviceLocked(null); + mPrimaryDisplayDevice = null; return; } @@ -686,28 +684,18 @@ final class LogicalDisplay { * @param targetDisplay The display with which to swap display-devices. * @return {@code true} if the displays were swapped, {@code false} otherwise. */ - public void swapDisplaysLocked(@NonNull LogicalDisplay targetDisplay) { - final DisplayDevice oldTargetDevice = - targetDisplay.setPrimaryDisplayDeviceLocked(mPrimaryDisplayDevice); - setPrimaryDisplayDeviceLocked(oldTargetDevice); - } - - /** - * Sets the primary display device to the specified device. - * - * @param device The new device to set. - * @return The previously set display device. - */ - public DisplayDevice setPrimaryDisplayDeviceLocked(@Nullable DisplayDevice device) { - final DisplayDevice old = mPrimaryDisplayDevice; - mPrimaryDisplayDevice = device; - - // Reset all our display info data - mPrimaryDisplayDeviceInfo = null; - mBaseDisplayInfo.copyFrom(EMPTY_DISPLAY_INFO); - mInfo.set(null); + public boolean swapDisplaysLocked(@NonNull LogicalDisplay targetDisplay) { + final DisplayDevice targetDevice = targetDisplay.getPrimaryDisplayDeviceLocked(); + if (mPrimaryDisplayDevice == null || targetDevice == null) { + Slog.e(TAG, "Missing display device during swap: " + mPrimaryDisplayDevice + " , " + + targetDevice); + return false; + } - return old; + final DisplayDevice tmpDevice = mPrimaryDisplayDevice; + mPrimaryDisplayDevice = targetDisplay.mPrimaryDisplayDevice; + targetDisplay.mPrimaryDisplayDevice = tmpDevice; + return true; } /** @@ -730,8 +718,8 @@ final class LogicalDisplay { public void dumpLocked(PrintWriter pw) { pw.println("mDisplayId=" + mDisplayId); - pw.println("mIsEnabled=" + mIsEnabled); pw.println("mLayerStack=" + mLayerStack); + pw.println("mIsEnabled=" + mIsEnabled); pw.println("mHasContent=" + mHasContent); pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}"); pw.println("mRequestedColorMode=" + mRequestedColorMode); diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index 22c12e93d0cc..a3ff534e336e 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -17,16 +17,13 @@ package com.android.server.display; import android.content.Context; -import android.hardware.devicestate.DeviceStateManager; import android.os.SystemProperties; import android.text.TextUtils; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; -import android.util.SparseBooleanArray; -import android.util.SparseIntArray; import android.view.Display; -import android.view.DisplayAddress; +import android.view.DisplayEventReceiver; import android.view.DisplayInfo; import com.android.server.display.layout.Layout; @@ -77,50 +74,24 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final boolean mSingleDisplayDemoMode; /** - * Map of all logical displays indexed by logical display id. + * List of all logical displays indexed by logical display id. * Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache. * TODO: multi-display - Move the aforementioned comment? */ private final SparseArray mLogicalDisplays = new SparseArray(); - /** Map of all display groups indexed by display group id. */ - private final SparseArray mDisplayGroups = new SparseArray<>(); + /** A mapping from logical display id to display group. */ + private final SparseArray mDisplayIdToGroupMap = new SparseArray<>(); private final DisplayDeviceRepository mDisplayDeviceRepo; private final DeviceStateToLayoutMap mDeviceStateToLayoutMap; private final Listener mListener; private final int[] mFoldedDeviceStates; - /** - * Has an entry for every logical display that the rest of the system has been notified about. - * Any entry in here requires us to send a {@link LOGICAL_DISPLAY_EVENT_REMOVED} event when it - * is deleted or {@link LOGICAL_DISPLAY_EVENT_CHANGED} when it is changed. - */ - private final SparseBooleanArray mUpdatedLogicalDisplays = new SparseBooleanArray(); - - /** - * Keeps track of all the display groups that we already told other people about. IOW, if a - * display group is in this array, then we *must* send change and remove notifications for it - * because other components know about them. Also, what this array stores is a change counter - * for each group, so we know if the group itself has changes since we last sent out a - * notification. See {@link DisplayGroup#getChangeCountLocked}. - */ - private final SparseIntArray mUpdatedDisplayGroups = new SparseIntArray(); - - /** - * Array used in {@link #updateLogicalDisplaysLocked} to track events that need to be sent out. - */ - private final SparseIntArray mLogicalDisplaysToUpdate = new SparseIntArray(); - - /** - * Array used in {@link #updateLogicalDisplaysLocked} to track events that need to be sent out. - */ - private final SparseIntArray mDisplayGroupsToUpdate = new SparseIntArray(); - private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; private Layout mCurrentLayout = null; - private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE; + private boolean mIsFolded = false; LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener) { mDisplayDeviceRepo = repo; @@ -138,23 +109,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { public void onDisplayDeviceEventLocked(DisplayDevice device, int event) { switch (event) { case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_ADDED: - if (DEBUG) { - Slog.d(TAG, "Display device added: " + device.getDisplayDeviceInfoLocked()); - } handleDisplayDeviceAddedLocked(device); break; case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_CHANGED: - if (DEBUG) { - Slog.d(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked()); - } updateLogicalDisplaysLocked(); break; case DisplayDeviceRepository.DISPLAY_DEVICE_EVENT_REMOVED: - if (DEBUG) { - Slog.d(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked()); - } updateLogicalDisplaysLocked(); break; } @@ -165,11 +127,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { mListener.onTraversalRequested(); } - public LogicalDisplay getDisplayLocked(int displayId) { + public LogicalDisplay getLocked(int displayId) { return mLogicalDisplays.get(displayId); } - public LogicalDisplay getDisplayLocked(DisplayDevice device) { + public LogicalDisplay getLocked(DisplayDevice device) { final int count = mLogicalDisplays.size(); for (int i = 0; i < count; i++) { LogicalDisplay display = mLogicalDisplays.valueAt(i); @@ -204,25 +166,16 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } } - public int getDisplayGroupIdFromDisplayIdLocked(int displayId) { - final LogicalDisplay display = getDisplayLocked(displayId); - if (display == null) { - return Display.INVALID_DISPLAY_GROUP; - } - - final int size = mDisplayGroups.size(); + public DisplayGroup getDisplayGroupLocked(int groupId) { + final int size = mDisplayIdToGroupMap.size(); for (int i = 0; i < size; i++) { - final DisplayGroup displayGroup = mDisplayGroups.valueAt(i); - if (displayGroup.containsLocked(display)) { - return mDisplayGroups.keyAt(i); + final DisplayGroup displayGroup = mDisplayIdToGroupMap.valueAt(i); + if (displayGroup.getGroupId() == groupId) { + return displayGroup; } } - return Display.INVALID_DISPLAY_GROUP; - } - - public DisplayGroup getDisplayGroupLocked(int groupId) { - return mDisplayGroups.get(groupId); + return null; } public void dumpLocked(PrintWriter pw) { @@ -250,333 +203,229 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { } void setDeviceStateLocked(int state) { - if (state != mDeviceState) { - resetLayoutLocked(); - mDeviceState = state; - applyLayoutLocked(); - updateLogicalDisplaysLocked(); + boolean folded = false; + for (int i = 0; i < mFoldedDeviceStates.length; i++) { + if (state == mFoldedDeviceStates[i]) { + folded = true; + break; + } } + setDeviceFoldedLocked(folded); } - private void handleDisplayDeviceAddedLocked(DisplayDevice device) { - DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); - // Internal Displays need to have additional initialization. - // TODO: b/168208162 - This initializes a default dynamic display layout for INTERNAL - // devices, which will eventually just be a fallback in case no static layout definitions - // exist or cannot be loaded. - if (deviceInfo.type == Display.TYPE_INTERNAL) { - initializeInternalDisplayDeviceLocked(device); - } + void setDeviceFoldedLocked(boolean isFolded) { + mIsFolded = isFolded; - // Create a logical display for the new display device - LogicalDisplay display = createNewLogicalDisplayLocked( - device, Layout.assignDisplayIdLocked(false /*isDefault*/)); + // Until we have fully functioning state mapping, use hardcoded states based on isFolded + final int state = mIsFolded ? DeviceStateToLayoutMap.STATE_FOLDED + : DeviceStateToLayoutMap.STATE_UNFOLDED; - applyLayoutLocked(); - updateLogicalDisplaysLocked(); - } - - /** - * Updates the rest of the display system once all the changes are applied for display - * devices and logical displays. The includes releasing invalid/empty LogicalDisplays, - * creating/adjusting/removing DisplayGroups, and notifying the rest of the system of the - * relevant changes. - */ - private void updateLogicalDisplaysLocked() { - // Go through all the displays and figure out if they need to be updated. - // Loops in reverse so that displays can be removed during the loop without affecting the - // rest of the loop. - for (int i = mLogicalDisplays.size() - 1; i >= 0; i--) { - final int displayId = mLogicalDisplays.keyAt(i); - LogicalDisplay display = mLogicalDisplays.valueAt(i); + if (DEBUG) { + Slog.d(TAG, "New device state: " + state); + } - mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); - display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo); + final Layout layout = mDeviceStateToLayoutMap.get(state); + if (layout == null) { + return; + } + final Layout.Display displayLayout = layout.getById(Display.DEFAULT_DISPLAY); + if (displayLayout == null) { + return; + } + final DisplayDevice newDefaultDevice = + mDisplayDeviceRepo.getByAddressLocked(displayLayout.getAddress()); + if (newDefaultDevice == null) { + return; + } - display.updateLocked(mDisplayDeviceRepo); - final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked(); - final boolean wasPreviouslyUpdated = mUpdatedLogicalDisplays.get(displayId); + final LogicalDisplay defaultDisplay = mLogicalDisplays.get(Display.DEFAULT_DISPLAY); + mCurrentLayout = layout; - // The display is no longer valid and needs to be removed. - if (!display.isValidLocked()) { - mUpdatedLogicalDisplays.delete(displayId); + // If we're already set up accurately, return early + if (defaultDisplay.getPrimaryDisplayDeviceLocked() == newDefaultDevice) { + return; + } - // Remove from group - final DisplayGroup displayGroup = getDisplayGroupLocked( - getDisplayGroupIdFromDisplayIdLocked(displayId)); - if (displayGroup != null) { - displayGroup.removeDisplayLocked(display); - } + // We need to swap the default display's display-device with the one that is supposed + // to be the default in the new layout. + final LogicalDisplay displayToSwap = getLocked(newDefaultDevice); + if (displayToSwap == null) { + Slog.w(TAG, "Canceling display swap - unexpected empty second display for: " + + newDefaultDevice); + return; + } + defaultDisplay.swapDisplaysLocked(displayToSwap); - if (wasPreviouslyUpdated) { - // The display isn't actually removed from our internal data structures until - // after the notification is sent; see {@link #sendUpdatesForDisplaysLocked}. - mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_REMOVED); - } else { - // This display never left this class, safe to remove without notification - mLogicalDisplays.removeAt(i); - } - continue; - - // The display is new. - } else if (!wasPreviouslyUpdated) { - assignDisplayGroupLocked(display); - mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_ADDED); - - // Underlying displays device has changed to a different one. - } else if (!TextUtils.equals(mTempDisplayInfo.uniqueId, newDisplayInfo.uniqueId)) { - // FLAG_OWN_DISPLAY_GROUP could have changed, recalculate just in case - assignDisplayGroupLocked(display); - mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_SWAPPED); - - // Something about the display device has changed. - } else if (!mTempDisplayInfo.equals(newDisplayInfo)) { - // FLAG_OWN_DISPLAY_GROUP could have changed, recalculate just in case - assignDisplayGroupLocked(display); - mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); - - // Display frame rate overrides changed. - } else if (!display.getPendingFrameRateOverrideUids().isEmpty()) { - mLogicalDisplaysToUpdate.put( - displayId, LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED); + // We ensure that the non-default Display is always forced to be off. This was likely + // already done in a previous iteration, but we do it with each swap in case something in + // the underlying LogicalDisplays changed: like LogicalDisplay recreation, for example. + defaultDisplay.setEnabled(true); + displayToSwap.setEnabled(false); - // Non-override display values changed. - } else { - // While application shouldn't know nor care about the non-overridden info, we - // still need to let WindowManager know so it can update its own internal state for - // things like display cutouts. - display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo); - if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) { - mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED); - } - } + // Update the world + updateLogicalDisplaysLocked(); + } - mUpdatedLogicalDisplays.put(displayId, true); + private void handleDisplayDeviceAddedLocked(DisplayDevice device) { + DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked(); + boolean isDefault = (deviceInfo.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; + if (isDefault && mLogicalDisplays.get(Display.DEFAULT_DISPLAY) != null) { + Slog.w(TAG, "Ignoring attempt to add a second default display: " + deviceInfo); + isDefault = false; } - // Go through the groups and do the same thing. We do this after displays since group - // information can change in the previous loop. - // Loops in reverse so that groups can be removed during the loop without affecting the - // rest of the loop. - for (int i = mDisplayGroups.size() - 1; i >= 0; i--) { - final int groupId = mDisplayGroups.keyAt(i); - final DisplayGroup group = mDisplayGroups.valueAt(i); - final boolean wasPreviouslyUpdated = mUpdatedDisplayGroups.indexOfKey(groupId) < 0; - final int changeCount = group.getChangeCountLocked(); - - if (group.isEmptyLocked()) { - mUpdatedDisplayGroups.delete(groupId); - if (wasPreviouslyUpdated) { - mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_REMOVED); - } - continue; - } else if (!wasPreviouslyUpdated) { - mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_ADDED); - } else if (mUpdatedDisplayGroups.get(groupId) != changeCount) { - mDisplayGroupsToUpdate.put(groupId, DISPLAY_GROUP_EVENT_CHANGED); - } - mUpdatedDisplayGroups.put(groupId, changeCount); + if (!isDefault && mSingleDisplayDemoMode) { + Slog.i(TAG, "Not creating a logical display for a secondary display " + + " because single display demo mode is enabled: " + deviceInfo); + return; } - // Send the display and display group updates in order by message type. This is important - // to ensure that addition and removal notifications happen in the right order. - sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED); - sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED); - sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED); - sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED); - sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED); - sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED); - sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED); - sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_REMOVED); - - mLogicalDisplaysToUpdate.clear(); - mDisplayGroupsToUpdate.clear(); - } - - /** - * Send the specified message for all relevant displays in the specified display-to-message map. - */ - private void sendUpdatesForDisplaysLocked(int msg) { - for (int i = mLogicalDisplaysToUpdate.size() - 1; i >= 0; --i) { - final int currMsg = mLogicalDisplaysToUpdate.valueAt(i); - if (currMsg != msg) { - continue; - } + final int displayId = Layout.assignDisplayIdLocked(isDefault); + final int layerStack = assignLayerStackLocked(displayId); - final int id = mLogicalDisplaysToUpdate.keyAt(i); - mListener.onLogicalDisplayEventLocked(getDisplayLocked(id), msg); - if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) { - // We wait until we sent the EVENT_REMOVED event before actually removing the - // display. - mLogicalDisplays.delete(id); - } + final DisplayGroup displayGroup; + final boolean addNewDisplayGroup = + isDefault || (deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0; + if (addNewDisplayGroup) { + final int groupId = assignDisplayGroupIdLocked(isDefault); + displayGroup = new DisplayGroup(groupId); + } else { + displayGroup = mDisplayIdToGroupMap.get(Display.DEFAULT_DISPLAY); } - } - - /** - * Send the specified message for all relevant display groups in the specified message map. - */ - private void sendUpdatesForGroupsLocked(int msg) { - for (int i = mDisplayGroupsToUpdate.size() - 1; i >= 0; --i) { - final int currMsg = mDisplayGroupsToUpdate.valueAt(i); - if (currMsg != msg) { - continue; - } - final int id = mDisplayGroupsToUpdate.keyAt(i); - mListener.onDisplayGroupEventLocked(id, msg); - if (msg == DISPLAY_GROUP_EVENT_REMOVED) { - // We wait until we sent the EVENT_REMOVED event before actually removing the - // group. - mDisplayGroups.delete(id); - } + LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); + display.updateDisplayGroupIdLocked(displayGroup.getGroupId()); + display.updateLocked(mDisplayDeviceRepo); + if (!display.isValidLocked()) { + // This should never happen currently. + Slog.w(TAG, "Ignoring display device because the logical display " + + "created from it was not considered valid: " + deviceInfo); + return; } - } - private void assignDisplayGroupLocked(LogicalDisplay display) { - final int displayId = display.getDisplayIdLocked(); + // For foldable devices, we start the internal non-default displays as disabled. + // TODO - b/168208162 - this will be removed when we recalculate the layout with each + // display-device addition. + if (mFoldedDeviceStates.length > 0 && deviceInfo.type == Display.TYPE_INTERNAL + && !isDefault) { + display.setEnabled(false); + } - // Get current display group data - int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId); - final DisplayGroup oldGroup = getDisplayGroupLocked(groupId); + mLogicalDisplays.put(displayId, display); + displayGroup.addDisplayLocked(display); + mDisplayIdToGroupMap.append(displayId, displayGroup); - // Get the new display group if a change is needed - final DisplayInfo info = display.getDisplayInfoLocked(); - final boolean needsOwnDisplayGroup = (info.flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0; - final boolean hasOwnDisplayGroup = groupId != Display.DEFAULT_DISPLAY_GROUP; - if (groupId == Display.INVALID_DISPLAY_GROUP - || hasOwnDisplayGroup != needsOwnDisplayGroup) { - groupId = assignDisplayGroupIdLocked(needsOwnDisplayGroup); + if (addNewDisplayGroup) { + // Group added events happen before Logical Display added events. + mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(), + LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED); } - // Create a new group if needed - DisplayGroup newGroup = getDisplayGroupLocked(groupId); - if (newGroup == null) { - newGroup = new DisplayGroup(groupId); - mDisplayGroups.append(groupId, newGroup); - } + mListener.onLogicalDisplayEventLocked(display, + LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED); - // Add/remove display from the groups. - newGroup.addDisplayLocked(display); - if (oldGroup != null && oldGroup != newGroup) { - oldGroup.removeDisplayLocked(display); + if (!addNewDisplayGroup) { + // Group changed events happen after Logical Display added events. + mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(), + LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED); } - } - /** - * Resets the current layout in preparation for a new layout; essentially just marks - * all the currently layed out displays as disabled. This ensures the display devices - * are turned off. If they are meant to be used in the new layout, - * {@link #applyLayoutLocked()} will reenabled them. - */ - private void resetLayoutLocked() { - final Layout layout = mDeviceStateToLayoutMap.get(mDeviceState); - for (int i = layout.size() - 1; i >= 0; i--) { - final Layout.Display displayLayout = layout.getAt(i); - final LogicalDisplay display = getDisplayLocked(displayLayout.getLogicalDisplayId()); - if (display != null) { - enableDisplayLocked(display, false); - } + if (DEBUG) { + Slog.d(TAG, "New Display added: " + display); } } - /** - * Apply (or reapply) the currently selected display layout. + * Updates all existing logical displays given the current set of display devices. + * Removes invalid logical displays. Sends notifications if needed. */ - private void applyLayoutLocked() { - final Layout layout = mDeviceStateToLayoutMap.get(mDeviceState); - mCurrentLayout = layout; - Slog.i(TAG, "Applying the display layout for device state(" + mDeviceState - + "): " + layout); + private void updateLogicalDisplaysLocked() { + for (int i = mLogicalDisplays.size() - 1; i >= 0; i--) { + final int displayId = mLogicalDisplays.keyAt(i); + LogicalDisplay display = mLogicalDisplays.valueAt(i); - // Go through each of the displays in the current layout set. - final int size = layout.size(); - for (int i = 0; i < size; i++) { - final Layout.Display displayLayout = layout.getAt(i); - - // If the underlying display-device we want to use for this display - // doesn't exist, then skip it. This can happen at startup as display-devices - // trickle in one at a time, or if the layout has an error. - final DisplayAddress address = displayLayout.getAddress(); - final DisplayDevice device = mDisplayDeviceRepo.getByAddressLocked(address); - if (device == null) { - Slog.w(TAG, "The display device (" + address + "), is not available" - + " for the display state " + mDeviceState); - continue; - } + mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked()); + display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo); + DisplayEventReceiver.FrameRateOverride[] frameRatesOverrides = + display.getFrameRateOverrides(); + display.updateLocked(mDisplayDeviceRepo); + final DisplayGroup changedDisplayGroup; + if (!display.isValidLocked()) { + mLogicalDisplays.removeAt(i); + final DisplayGroup displayGroup = mDisplayIdToGroupMap.removeReturnOld(displayId); + displayGroup.removeDisplayLocked(display); + + mListener.onLogicalDisplayEventLocked(display, + LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED); + + changedDisplayGroup = displayGroup; + } else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) { + final int flags = display.getDisplayInfoLocked().flags; + final DisplayGroup defaultDisplayGroup = mDisplayIdToGroupMap.get( + Display.DEFAULT_DISPLAY); + if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) { + // The display should have its own DisplayGroup. + if (defaultDisplayGroup.removeDisplayLocked(display)) { + final int groupId = assignDisplayGroupIdLocked(false); + final DisplayGroup displayGroup = new DisplayGroup(groupId); + displayGroup.addDisplayLocked(display); + display.updateDisplayGroupIdLocked(groupId); + mDisplayIdToGroupMap.append(display.getDisplayIdLocked(), displayGroup); + mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(), + LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED); + changedDisplayGroup = defaultDisplayGroup; + } else { + changedDisplayGroup = null; + } + } else { + // The display should be a part of the default DisplayGroup. + final DisplayGroup displayGroup = mDisplayIdToGroupMap.get(displayId); + if (displayGroup != defaultDisplayGroup) { + displayGroup.removeDisplayLocked(display); + defaultDisplayGroup.addDisplayLocked(display); + display.updateDisplayGroupIdLocked(defaultDisplayGroup.getGroupId()); + mListener.onDisplayGroupEventLocked(defaultDisplayGroup.getGroupId(), + LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED); + mDisplayIdToGroupMap.put(displayId, defaultDisplayGroup); + changedDisplayGroup = displayGroup; + } else { + changedDisplayGroup = null; + } + } - // Now that we have a display-device, we need a LogicalDisplay to map it to. Find the - // right one, if it doesn't exist, create a new one. - final int logicalDisplayId = displayLayout.getLogicalDisplayId(); - LogicalDisplay newDisplay = getDisplayLocked(logicalDisplayId); - if (newDisplay == null) { - newDisplay = createNewLogicalDisplayLocked( - null /*displayDevice*/, logicalDisplayId); + final String oldUniqueId = mTempDisplayInfo.uniqueId; + final String newUniqueId = display.getDisplayInfoLocked().uniqueId; + final int eventMsg = TextUtils.equals(oldUniqueId, newUniqueId) + ? LOGICAL_DISPLAY_EVENT_CHANGED : LOGICAL_DISPLAY_EVENT_SWAPPED; + mListener.onLogicalDisplayEventLocked(display, eventMsg); + } else if (!display.getPendingFrameRateOverrideUids().isEmpty()) { + mListener.onLogicalDisplayEventLocked(display, + LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED); + changedDisplayGroup = null; + } else { + // While applications shouldn't know nor care about the non-overridden info, we + // still need to let WindowManager know so it can update its own internal state for + // things like display cutouts. + display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo); + if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) { + mListener.onLogicalDisplayEventLocked(display, + LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED); + } + changedDisplayGroup = null; } - // Now swap the underlying display devices between the old display and the new display - final LogicalDisplay oldDisplay = getDisplayLocked(device); - if (newDisplay != oldDisplay) { - newDisplay.swapDisplaysLocked(oldDisplay); + // CHANGED and REMOVED DisplayGroup events should always fire after Display events. + if (changedDisplayGroup != null) { + final int event = changedDisplayGroup.isEmptyLocked() + ? LogicalDisplayMapper.DISPLAY_GROUP_EVENT_REMOVED + : LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED; + mListener.onDisplayGroupEventLocked(changedDisplayGroup.getGroupId(), event); } - enableDisplayLocked(newDisplay, true); } } - - /** - * Creates a new logical display for the specified device and display Id and adds it to the list - * of logical displays. - * - * @param device The device to associate with the LogicalDisplay. - * @param displayId The display ID to give the new display. If invalid, a new ID is assigned. - * @param isDefault Indicates if we are creating the default display. - * @return The new logical display if created, null otherwise. - */ - private LogicalDisplay createNewLogicalDisplayLocked(DisplayDevice device, int displayId) { - final int layerStack = assignLayerStackLocked(displayId); - final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device); - display.updateLocked(mDisplayDeviceRepo); - mLogicalDisplays.put(displayId, display); - - // Internal displays start off disabled. The display is enabled later if it is part of the - // currently selected display layout. - final boolean isEnabled = device != null - && device.getDisplayDeviceInfoLocked().type != Display.TYPE_INTERNAL; - enableDisplayLocked(display, isEnabled); - - return display; - } - - private void enableDisplayLocked(LogicalDisplay display, boolean isEnabled) { - final int displayId = display.getDisplayIdLocked(); - final DisplayInfo info = display.getDisplayInfoLocked(); - - final boolean disallowSecondaryDisplay = mSingleDisplayDemoMode - && (info.type != Display.TYPE_INTERNAL); - if (isEnabled && disallowSecondaryDisplay) { - Slog.i(TAG, "Not creating a logical display for a secondary display because single" - + " display demo mode is enabled: " + display.getDisplayInfoLocked()); - isEnabled = false; - } - - display.setEnabled(isEnabled); - } - - private int assignDisplayGroupIdLocked(boolean isOwnDisplayGroup) { - return isOwnDisplayGroup ? mNextNonDefaultGroupId++ : Display.DEFAULT_DISPLAY_GROUP; - } - - private void initializeInternalDisplayDeviceLocked(DisplayDevice device) { - // We always want to make sure that our default display layout creates a logical - // display for every internal display device that is found. - // To that end, when we are notified of a new internal display, we add it to - // the default definition if it is not already there. - final Layout layoutSet = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT); - final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked(); - final boolean isDefault = (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0; - layoutSet.createDisplayLocked(info.address, isDefault); + private int assignDisplayGroupIdLocked(boolean isDefault) { + return isDefault ? Display.DEFAULT_DISPLAY_GROUP : mNextNonDefaultGroupId++; } private int assignLayerStackLocked(int displayId) { diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java deleted file mode 100644 index 92221c9713d3..000000000000 --- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.display; - -import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED; -import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED; -import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED; -import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED; -import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.verify; - -import android.app.PropertyInvalidatedCache; -import android.content.Context; -import android.os.Parcel; -import android.os.Process; -import android.platform.test.annotations.Presubmit; -import android.view.Display; -import android.view.DisplayAddress; -import android.view.DisplayInfo; - -import androidx.test.InstrumentationRegistry; -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; - -@SmallTest -@Presubmit -@RunWith(AndroidJUnit4.class) -public class LogicalDisplayMapperTest { - private static int sUniqueTestDisplayId = 0; - - private DisplayDeviceRepository mDisplayDeviceRepo; - private LogicalDisplayMapper mLogicalDisplayMapper; - private Context mContext; - - @Mock LogicalDisplayMapper.Listener mListenerMock; - - @Captor ArgumentCaptor mDisplayCaptor; - - @Before - public void setUp() { - // Share classloader to allow package private access. - System.setProperty("dexmaker.share_classloader", "true"); - MockitoAnnotations.initMocks(this); - - mContext = InstrumentationRegistry.getContext(); - mDisplayDeviceRepo = new DisplayDeviceRepository( - new DisplayManagerService.SyncRoot(), - new PersistentDataStore(new PersistentDataStore.Injector() { - @Override - public InputStream openRead() { - return null; - } - - @Override - public OutputStream startWrite() { - return null; - } - - @Override - public void finishWrite(OutputStream os, boolean success) {} - })); - - // Disable binder caches in this process. - PropertyInvalidatedCache.disableForTestMode(); - - mLogicalDisplayMapper = new LogicalDisplayMapper( - mContext, mDisplayDeviceRepo, mListenerMock); - } - - - ///////////////// - // Test Methods - ///////////////// - - @Test - public void testDisplayDeviceAddAndRemove_Internal() { - DisplayDevice device = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY); - - // add - LogicalDisplay displayAdded = add(device); - assertEquals(info(displayAdded).address, info(device).address); - assertEquals(Display.DEFAULT_DISPLAY, id(displayAdded)); - - // remove - mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED); - verify(mListenerMock).onLogicalDisplayEventLocked( - mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED)); - LogicalDisplay displayRemoved = mDisplayCaptor.getValue(); - assertEquals(Display.DEFAULT_DISPLAY, id(displayRemoved)); - assertEquals(displayAdded, displayRemoved); - } - - @Test - public void testDisplayDeviceAddAndRemove_NonInternalTypes() { - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_EXTERNAL); - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_WIFI); - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_OVERLAY); - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_VIRTUAL); - testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_UNKNOWN); - - // Call the internal test again, just to verify that adding non-internal displays - // doesn't affect the ability for an internal display to become the default display. - testDisplayDeviceAddAndRemove_Internal(); - } - - @Test - public void testDisplayDeviceAdd_TwoInternalOneDefault() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY); - - LogicalDisplay display1 = add(device1); - assertEquals(info(display1).address, info(device1).address); - assertNotEquals(Display.DEFAULT_DISPLAY, id(display1)); - - LogicalDisplay display2 = add(device2); - assertEquals(info(display2).address, info(device2).address); - assertEquals(Display.DEFAULT_DISPLAY, id(display2)); - } - - @Test - public void testDisplayDeviceAdd_TwoInternalBothDefault() { - DisplayDevice device1 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY); - DisplayDevice device2 = createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY); - - LogicalDisplay display1 = add(device1); - assertEquals(info(display1).address, info(device1).address); - assertEquals(Display.DEFAULT_DISPLAY, id(display1)); - - LogicalDisplay display2 = add(device2); - assertEquals(info(display2).address, info(device2).address); - // Despite the flags, we can only have one default display - assertNotEquals(Display.DEFAULT_DISPLAY, id(display2)); - } - - @Test - public void testGetDisplayIdsLocked() { - add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - add(createDisplayDevice(Display.TYPE_EXTERNAL, 600, 800, 0)); - add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0)); - - int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID); - assertEquals(3, ids.length); - Arrays.sort(ids); - assertEquals(Display.DEFAULT_DISPLAY, ids[0]); - } - - @Test - public void testSingleDisplayGroup() { - LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0)); - LogicalDisplay display3 = add(createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, 0)); - - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1))); - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2))); - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); - } - - @Test - public void testMultipleDisplayGroups() { - LogicalDisplay display1 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, - DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY)); - LogicalDisplay display2 = add(createDisplayDevice(Display.TYPE_INTERNAL, 600, 800, 0)); - - - TestDisplayDevice device3 = createDisplayDevice(Display.TYPE_VIRTUAL, 600, 800, - DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP); - LogicalDisplay display3 = add(device3); - - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1))); - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2))); - assertNotEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); - - // Now switch it back to the default group by removing the flag and issuing an update - DisplayDeviceInfo info = device3.getSourceInfo(); - info.flags = info.flags & ~DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP; - mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED); - - // Verify the new group is correct. - assertEquals(Display.DEFAULT_DISPLAY_GROUP, - mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3))); - } - - - ///////////////// - // Helper Methods - ///////////////// - - private TestDisplayDevice createDisplayDevice(int type, int width, int height, int flags) { - return createDisplayDevice(new DisplayAddressImpl(), type, width, height, flags); - } - - private TestDisplayDevice createDisplayDevice( - DisplayAddress address, int type, int width, int height, int flags) { - TestDisplayDevice device = new TestDisplayDevice(); - DisplayDeviceInfo displayDeviceInfo = device.getSourceInfo(); - displayDeviceInfo.type = type; - displayDeviceInfo.width = width; - displayDeviceInfo.height = height; - displayDeviceInfo.flags = flags; - displayDeviceInfo.address = new DisplayAddressImpl(); - return device; - } - - private DisplayDeviceInfo info(DisplayDevice device) { - return device.getDisplayDeviceInfoLocked(); - } - - private DisplayInfo info(LogicalDisplay display) { - return display.getDisplayInfoLocked(); - } - - private int id(LogicalDisplay display) { - return display.getDisplayIdLocked(); - } - - private LogicalDisplay add(DisplayDevice device) { - mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_ADDED); - ArgumentCaptor displayCaptor = - ArgumentCaptor.forClass(LogicalDisplay.class); - verify(mListenerMock).onLogicalDisplayEventLocked( - displayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_ADDED)); - clearInvocations(mListenerMock); - return displayCaptor.getValue(); - } - - private void testDisplayDeviceAddAndRemove_NonInternal(int type) { - DisplayDevice device = createDisplayDevice(type, 600, 800, 0); - - // add - LogicalDisplay displayAdded = add(device); - assertEquals(info(displayAdded).address, info(device).address); - assertNotEquals(Display.DEFAULT_DISPLAY, id(displayAdded)); - - // remove - mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED); - verify(mListenerMock).onLogicalDisplayEventLocked( - mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED)); - LogicalDisplay displayRemoved = mDisplayCaptor.getValue(); - assertNotEquals(Display.DEFAULT_DISPLAY, id(displayRemoved)); - } - - /** - * Create a custom {@link DisplayAddress} to ensure we're not relying on any specific - * display-address implementation in our code. Intentionally uses default object (reference) - * equality rules. - */ - class DisplayAddressImpl extends DisplayAddress { - @Override - public void writeToParcel(Parcel out, int flags) { } - } - - class TestDisplayDevice extends DisplayDevice { - private DisplayDeviceInfo mInfo = new DisplayDeviceInfo(); - private DisplayDeviceInfo mSentInfo; - - TestDisplayDevice() { - super(null, null, "test_display_" + sUniqueTestDisplayId++, mContext); - mInfo = new DisplayDeviceInfo(); - } - - @Override - public DisplayDeviceInfo getDisplayDeviceInfoLocked() { - if (mSentInfo == null) { - mSentInfo = new DisplayDeviceInfo(); - mSentInfo.copyFrom(mInfo); - } - return mSentInfo; - } - - @Override - public void applyPendingDisplayDeviceInfoChangesLocked() { - mSentInfo = null; - } - - @Override - public boolean hasStableUniqueId() { - return true; - } - - public DisplayDeviceInfo getSourceInfo() { - return mInfo; - } - } -} - -- GitLab