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
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,15 +673,6 @@
|
||||
-->
|
||||
</integer-array>
|
||||
|
||||
<!-- The device states (supplied by DeviceStateManager) that should be treated as unfolded by
|
||||
the display fold controller. Default is empty. -->
|
||||
<integer-array name="config_unfoldedDeviceStates">
|
||||
<!-- Example:
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
-->
|
||||
</integer-array>
|
||||
|
||||
<!-- Indicate the display area rect for foldable devices in folded state. -->
|
||||
<string name="config_foldedArea"></string>
|
||||
|
||||
|
||||
@@ -3762,7 +3762,6 @@
|
||||
|
||||
<!-- For Foldables -->
|
||||
<java-symbol type="array" name="config_foldedDeviceStates" />
|
||||
<java-symbol type="array" name="config_unfoldedDeviceStates" />
|
||||
<java-symbol type="string" name="config_foldedArea" />
|
||||
|
||||
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
|
||||
|
||||
@@ -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<Layout> 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*/);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ public class DisplayGroup {
|
||||
private final List<LogicalDisplay> 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();
|
||||
|
||||
@@ -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<Integer> 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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
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);
|
||||
|
||||
@@ -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<LogicalDisplay> mLogicalDisplays =
|
||||
new SparseArray<LogicalDisplay>();
|
||||
|
||||
/** Map of all display groups indexed by display group id. */
|
||||
private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>();
|
||||
/** A mapping from logical display id to display group. */
|
||||
private final SparseArray<DisplayGroup> 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);
|
||||
}
|
||||
|
||||
void setDeviceFoldedLocked(boolean isFolded) {
|
||||
mIsFolded = isFolded;
|
||||
|
||||
// Until we have fully functioning state mapping, use hardcoded states based on isFolded
|
||||
final int state = mIsFolded ? DeviceStateToLayoutMap.STATE_FOLDED
|
||||
: DeviceStateToLayoutMap.STATE_UNFOLDED;
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "New device state: " + state);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
final LogicalDisplay defaultDisplay = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
|
||||
mCurrentLayout = layout;
|
||||
|
||||
// If we're already set up accurately, return early
|
||||
if (defaultDisplay.getPrimaryDisplayDeviceLocked() == newDefaultDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// Update the world
|
||||
updateLogicalDisplaysLocked();
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
// Create a logical display for the new display device
|
||||
LogicalDisplay display = createNewLogicalDisplayLocked(
|
||||
device, Layout.assignDisplayIdLocked(false /*isDefault*/));
|
||||
if (!isDefault && mSingleDisplayDemoMode) {
|
||||
Slog.i(TAG, "Not creating a logical display for a secondary display "
|
||||
+ " because single display demo mode is enabled: " + deviceInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
applyLayoutLocked();
|
||||
updateLogicalDisplaysLocked();
|
||||
final int displayId = Layout.assignDisplayIdLocked(isDefault);
|
||||
final int layerStack = assignLayerStackLocked(displayId);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
mLogicalDisplays.put(displayId, display);
|
||||
displayGroup.addDisplayLocked(display);
|
||||
mDisplayIdToGroupMap.append(displayId, displayGroup);
|
||||
|
||||
if (addNewDisplayGroup) {
|
||||
// Group added events happen before Logical Display added events.
|
||||
mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(),
|
||||
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_ADDED);
|
||||
}
|
||||
|
||||
mListener.onLogicalDisplayEventLocked(display,
|
||||
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED);
|
||||
|
||||
if (!addNewDisplayGroup) {
|
||||
// Group changed events happen after Logical Display added events.
|
||||
mListener.onDisplayGroupEventLocked(displayGroup.getGroupId(),
|
||||
LogicalDisplayMapper.DISPLAY_GROUP_EVENT_CHANGED);
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "New Display added: " + display);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Updates all existing logical displays given the current set of display devices.
|
||||
* Removes invalid logical displays. Sends notifications if needed.
|
||||
*/
|
||||
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);
|
||||
|
||||
mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
|
||||
display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);
|
||||
|
||||
DisplayEventReceiver.FrameRateOverride[] frameRatesOverrides =
|
||||
display.getFrameRateOverrides();
|
||||
display.updateLocked(mDisplayDeviceRepo);
|
||||
final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
|
||||
final boolean wasPreviouslyUpdated = mUpdatedLogicalDisplays.get(displayId);
|
||||
|
||||
// The display is no longer valid and needs to be removed.
|
||||
final DisplayGroup changedDisplayGroup;
|
||||
if (!display.isValidLocked()) {
|
||||
mUpdatedLogicalDisplays.delete(displayId);
|
||||
mLogicalDisplays.removeAt(i);
|
||||
final DisplayGroup displayGroup = mDisplayIdToGroupMap.removeReturnOld(displayId);
|
||||
displayGroup.removeDisplayLocked(display);
|
||||
|
||||
// Remove from group
|
||||
final DisplayGroup displayGroup = getDisplayGroupLocked(
|
||||
getDisplayGroupIdFromDisplayIdLocked(displayId));
|
||||
if (displayGroup != null) {
|
||||
displayGroup.removeDisplayLocked(display);
|
||||
}
|
||||
mListener.onLogicalDisplayEventLocked(display,
|
||||
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED);
|
||||
|
||||
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);
|
||||
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 {
|
||||
// This display never left this class, safe to remove without notification
|
||||
mLogicalDisplays.removeAt(i);
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
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.
|
||||
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()) {
|
||||
mLogicalDisplaysToUpdate.put(
|
||||
displayId, LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
|
||||
|
||||
// Non-override display values changed.
|
||||
mListener.onLogicalDisplayEventLocked(display,
|
||||
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
|
||||
changedDisplayGroup = null;
|
||||
} else {
|
||||
// While application shouldn't know nor care about the non-overridden info, we
|
||||
// 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)) {
|
||||
mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);
|
||||
mListener.onLogicalDisplayEventLocked(display,
|
||||
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_CHANGED);
|
||||
}
|
||||
changedDisplayGroup = null;
|
||||
}
|
||||
|
||||
mUpdatedLogicalDisplays.put(displayId, true);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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 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);
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assignDisplayGroupLocked(LogicalDisplay display) {
|
||||
final int displayId = display.getDisplayIdLocked();
|
||||
|
||||
// Get current display group data
|
||||
int groupId = getDisplayGroupIdFromDisplayIdLocked(displayId);
|
||||
final DisplayGroup oldGroup = getDisplayGroupLocked(groupId);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Create a new group if needed
|
||||
DisplayGroup newGroup = getDisplayGroupLocked(groupId);
|
||||
if (newGroup == null) {
|
||||
newGroup = new DisplayGroup(groupId);
|
||||
mDisplayGroups.append(groupId, newGroup);
|
||||
}
|
||||
|
||||
// Add/remove display from the groups.
|
||||
newGroup.addDisplayLocked(display);
|
||||
if (oldGroup != null && oldGroup != newGroup) {
|
||||
oldGroup.removeDisplayLocked(display);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply (or reapply) the currently selected display layout.
|
||||
*/
|
||||
private void applyLayoutLocked() {
|
||||
final Layout layout = mDeviceStateToLayoutMap.get(mDeviceState);
|
||||
mCurrentLayout = layout;
|
||||
Slog.i(TAG, "Applying the display layout for device state(" + mDeviceState
|
||||
+ "): " + layout);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
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) {
|
||||
|
||||
@@ -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<LogicalDisplay> 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<LogicalDisplay> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user