Merge "Turn OFF any changing displays during device-state transitions" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
b4bed4d455
@@ -657,6 +657,12 @@
|
|||||||
<!-- Indicate the display area rect for foldable devices in folded state. -->
|
<!-- Indicate the display area rect for foldable devices in folded state. -->
|
||||||
<string name="config_foldedArea"></string>
|
<string name="config_foldedArea"></string>
|
||||||
|
|
||||||
|
<!-- Indicates that the device supports having more than one internal display on at the same
|
||||||
|
time. Only applicable to devices with more than one internal display. If this option is
|
||||||
|
set to false, DisplayManager will make additional effort to ensure no more than 1 internal
|
||||||
|
display is powered on at the same time. -->
|
||||||
|
<bool name="config_supportsConcurrentInternalDisplays">true</bool>
|
||||||
|
|
||||||
<!-- Desk dock behavior -->
|
<!-- Desk dock behavior -->
|
||||||
|
|
||||||
<!-- The number of degrees to rotate the display when the device is in a desk dock.
|
<!-- The number of degrees to rotate the display when the device is in a desk dock.
|
||||||
|
|||||||
@@ -3800,6 +3800,7 @@
|
|||||||
<!-- For Foldables -->
|
<!-- For Foldables -->
|
||||||
<java-symbol type="array" name="config_foldedDeviceStates" />
|
<java-symbol type="array" name="config_foldedDeviceStates" />
|
||||||
<java-symbol type="string" name="config_foldedArea" />
|
<java-symbol type="string" name="config_foldedArea" />
|
||||||
|
<java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" />
|
||||||
|
|
||||||
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
|
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
|
||||||
<java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
|
<java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
|
||||||
|
|||||||
@@ -431,8 +431,8 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
|
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
|
||||||
mUiHandler = UiThread.getHandler();
|
mUiHandler = UiThread.getHandler();
|
||||||
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
|
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
|
||||||
mLogicalDisplayMapper = new LogicalDisplayMapper(mDisplayDeviceRepo,
|
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
|
||||||
new LogicalDisplayListener());
|
new LogicalDisplayListener(), mSyncRoot, mHandler);
|
||||||
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
|
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
|
||||||
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
|
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
|
||||||
Resources resources = mContext.getResources();
|
Resources resources = mContext.getResources();
|
||||||
@@ -1268,7 +1268,7 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
|
|
||||||
DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
|
DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
|
||||||
if (dpc != null) {
|
if (dpc != null) {
|
||||||
dpc.onDisplayChangedLocked();
|
dpc.onDisplayChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,12 +1304,23 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
handleLogicalDisplayChangedLocked(display);
|
handleLogicalDisplayChangedLocked(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
|
||||||
|
final int displayId = display.getDisplayIdLocked();
|
||||||
|
final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
|
||||||
|
if (dpc != null) {
|
||||||
|
dpc.onDeviceStateTransition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Runnable updateDisplayStateLocked(DisplayDevice device) {
|
private Runnable updateDisplayStateLocked(DisplayDevice device) {
|
||||||
// Blank or unblank the display immediately to match the state requested
|
// Blank or unblank the display immediately to match the state requested
|
||||||
// by the display power controller (if known).
|
// by the display power controller (if known).
|
||||||
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
||||||
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
|
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
|
||||||
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
|
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
|
||||||
|
if (display == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final int displayId = display.getDisplayIdLocked();
|
final int displayId = display.getDisplayIdLocked();
|
||||||
final int state = mDisplayStates.get(displayId);
|
final int state = mDisplayStates.get(displayId);
|
||||||
|
|
||||||
@@ -1453,9 +1464,12 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
clearViewportsLocked();
|
clearViewportsLocked();
|
||||||
|
|
||||||
// Configure each display device.
|
// Configure each display device.
|
||||||
mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
|
mLogicalDisplayMapper.forEachLocked((LogicalDisplay display) -> {
|
||||||
configureDisplayLocked(t, device);
|
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||||
device.performTraversalLocked(t);
|
if (device != null) {
|
||||||
|
configureDisplayLocked(t, device);
|
||||||
|
device.performTraversalLocked(t);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Tell the input system about these new viewports.
|
// Tell the input system about these new viewports.
|
||||||
@@ -2159,6 +2173,10 @@ public final class DisplayManagerService extends SystemService {
|
|||||||
case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
|
case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
|
||||||
handleLogicalDisplayFrameRateOverridesChangedLocked(display);
|
handleLogicalDisplayFrameRateOverridesChangedLocked(display);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION:
|
||||||
|
handleLogicalDisplayDeviceStateTransitionLocked(display);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -780,15 +780,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
|||||||
* when displays get swapped on foldable devices. For example, different brightness properties
|
* when displays get swapped on foldable devices. For example, different brightness properties
|
||||||
* of each display need to be properly reflected in AutomaticBrightnessController.
|
* of each display need to be properly reflected in AutomaticBrightnessController.
|
||||||
*/
|
*/
|
||||||
public void onDisplayChangedLocked() {
|
public void onDisplayChanged() {
|
||||||
// TODO: b/175821789 - Support high brightness on multiple (folding) displays
|
// TODO: b/175821789 - Support high brightness on multiple (folding) displays
|
||||||
|
|
||||||
mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
|
mUniqueDisplayId = mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
|
||||||
mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked()
|
mDisplayDeviceConfig = mLogicalDisplay.getPrimaryDisplayDeviceLocked()
|
||||||
.getDisplayDeviceConfig();
|
.getDisplayDeviceConfig();
|
||||||
loadAmbientLightSensor();
|
loadAmbientLightSensor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the displays are preparing to transition from one device state to another.
|
||||||
|
* This process involves turning off some displays so we need updatePowerState() to run and
|
||||||
|
* calculate the new state.
|
||||||
|
*/
|
||||||
|
public void onDeviceStateTransition() {
|
||||||
|
sendUpdatePowerState();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unregisters all listeners and interrupts all running threads; halting future work.
|
* Unregisters all listeners and interrupts all running threads; halting future work.
|
||||||
*
|
*
|
||||||
@@ -1024,7 +1032,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
|||||||
mIgnoreProximityUntilChanged = false;
|
mIgnoreProximityUntilChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mLogicalDisplay.isEnabled() || mScreenOffBecauseOfProximity) {
|
if (!mLogicalDisplay.isEnabled()
|
||||||
|
|| mLogicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION
|
||||||
|
|| mScreenOffBecauseOfProximity) {
|
||||||
state = Display.STATE_OFF;
|
state = Display.STATE_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.display;
|
package com.android.server.display;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
@@ -65,6 +66,33 @@ import java.util.Objects;
|
|||||||
final class LogicalDisplay {
|
final class LogicalDisplay {
|
||||||
private static final String TAG = "LogicalDisplay";
|
private static final String TAG = "LogicalDisplay";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phase indicating the logical display's existence is hidden from the rest of the framework.
|
||||||
|
* This can happen if the current layout has specifically requested to keep this display
|
||||||
|
* disabled.
|
||||||
|
*/
|
||||||
|
static final int DISPLAY_PHASE_DISABLED = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Phase indicating that the logical display is going through a layout transition.
|
||||||
|
* When in this phase, other systems can choose to special case power-state handling of a
|
||||||
|
* display that might be in a transition.
|
||||||
|
*/
|
||||||
|
static final int DISPLAY_PHASE_LAYOUT_TRANSITION = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display is exposed to the rest of the system and its power state is determined by a
|
||||||
|
* power-request from PowerManager.
|
||||||
|
*/
|
||||||
|
static final int DISPLAY_PHASE_ENABLED = 1;
|
||||||
|
|
||||||
|
@IntDef(prefix = {"DISPLAY_PHASE" }, value = {
|
||||||
|
DISPLAY_PHASE_DISABLED,
|
||||||
|
DISPLAY_PHASE_LAYOUT_TRANSITION,
|
||||||
|
DISPLAY_PHASE_ENABLED
|
||||||
|
})
|
||||||
|
@interface DisplayPhase {}
|
||||||
|
|
||||||
// The layer stack we use when the display has been blanked to prevent any
|
// The layer stack we use when the display has been blanked to prevent any
|
||||||
// of its content from appearing.
|
// of its content from appearing.
|
||||||
private static final int BLANK_LAYER_STACK = -1;
|
private static final int BLANK_LAYER_STACK = -1;
|
||||||
@@ -129,10 +157,12 @@ final class LogicalDisplay {
|
|||||||
private final Rect mTempDisplayRect = new Rect();
|
private final Rect mTempDisplayRect = new Rect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the Logical display is enabled (default). See {@link #setEnabled} for
|
* Indicates the current phase of the display. Generally, phases supersede any
|
||||||
* more information.
|
* requests from PowerManager in DPC's calculation for the display state. Only when the
|
||||||
|
* phase is ENABLED does PowerManager's request for the display take effect.
|
||||||
*/
|
*/
|
||||||
private boolean mIsEnabled = true;
|
@DisplayPhase
|
||||||
|
private int mPhase = DISPLAY_PHASE_ENABLED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The UID mappings for refresh rate override
|
* The UID mappings for refresh rate override
|
||||||
@@ -721,27 +751,32 @@ final class LogicalDisplay {
|
|||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setPhase(@DisplayPhase int phase) {
|
||||||
* Sets the LogicalDisplay to be enabled or disabled. If the display is not enabled,
|
mPhase = phase;
|
||||||
* the system will always set the display to power off, regardless of the global state of the
|
|
||||||
* device.
|
|
||||||
* TODO: b/170498827 - Remove when updateDisplayStateLocked is updated.
|
|
||||||
*/
|
|
||||||
public void setEnabled(boolean isEnabled) {
|
|
||||||
mIsEnabled = isEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@code true} iff the LogicalDisplay is enabled or {@code false}
|
* Returns the currently set phase for this LogicalDisplay. Phases are used when transitioning
|
||||||
* if disabled indicating that the display has been forced to be OFF.
|
* from one device state to another. {@see LogicalDisplayMapper}.
|
||||||
|
*/
|
||||||
|
@DisplayPhase
|
||||||
|
public int getPhase() {
|
||||||
|
return mPhase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@code true} if the LogicalDisplay is enabled or {@code false}
|
||||||
|
* if disabled indicating that the display should be hidden from the rest of the apps and
|
||||||
|
* framework.
|
||||||
*/
|
*/
|
||||||
public boolean isEnabled() {
|
public boolean isEnabled() {
|
||||||
return mIsEnabled;
|
// DISPLAY_PHASE_LAYOUT_TRANSITION is still considered an 'enabled' phase.
|
||||||
|
return mPhase == DISPLAY_PHASE_ENABLED || mPhase == DISPLAY_PHASE_LAYOUT_TRANSITION;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpLocked(PrintWriter pw) {
|
public void dumpLocked(PrintWriter pw) {
|
||||||
pw.println("mDisplayId=" + mDisplayId);
|
pw.println("mDisplayId=" + mDisplayId);
|
||||||
pw.println("mIsEnabled=" + mIsEnabled);
|
pw.println("mPhase=" + mPhase);
|
||||||
pw.println("mLayerStack=" + mLayerStack);
|
pw.println("mLayerStack=" + mLayerStack);
|
||||||
pw.println("mHasContent=" + mHasContent);
|
pw.println("mHasContent=" + mHasContent);
|
||||||
pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
|
pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
|
||||||
|
|||||||
@@ -16,18 +16,24 @@
|
|||||||
|
|
||||||
package com.android.server.display;
|
package com.android.server.display;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.content.Context;
|
||||||
import android.hardware.devicestate.DeviceStateManager;
|
import android.hardware.devicestate.DeviceStateManager;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.SparseBooleanArray;
|
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayAddress;
|
import android.view.DisplayAddress;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
import com.android.server.display.LogicalDisplay.DisplayPhase;
|
||||||
import com.android.server.display.layout.Layout;
|
import com.android.server.display.layout.Layout;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -55,11 +61,20 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
public static final int LOGICAL_DISPLAY_EVENT_REMOVED = 3;
|
public static final int LOGICAL_DISPLAY_EVENT_REMOVED = 3;
|
||||||
public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 4;
|
public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 4;
|
||||||
public static final int LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED = 5;
|
public static final int LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED = 5;
|
||||||
|
public static final int LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION = 6;
|
||||||
|
|
||||||
public static final int DISPLAY_GROUP_EVENT_ADDED = 1;
|
public static final int DISPLAY_GROUP_EVENT_ADDED = 1;
|
||||||
public static final int DISPLAY_GROUP_EVENT_CHANGED = 2;
|
public static final int DISPLAY_GROUP_EVENT_CHANGED = 2;
|
||||||
public static final int DISPLAY_GROUP_EVENT_REMOVED = 3;
|
public static final int DISPLAY_GROUP_EVENT_REMOVED = 3;
|
||||||
|
|
||||||
|
private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500;
|
||||||
|
|
||||||
|
private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1;
|
||||||
|
|
||||||
|
private static final int UPDATE_STATE_NEW = 0;
|
||||||
|
private static final int UPDATE_STATE_TRANSITION = 1;
|
||||||
|
private static final int UPDATE_STATE_UPDATED = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Temporary display info, used for comparing display configurations.
|
* Temporary display info, used for comparing display configurations.
|
||||||
*/
|
*/
|
||||||
@@ -75,6 +90,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
*/
|
*/
|
||||||
private final boolean mSingleDisplayDemoMode;
|
private final boolean mSingleDisplayDemoMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the device can have more than one internal display on at a time.
|
||||||
|
*/
|
||||||
|
private final boolean mSupportsConcurrentInternalDisplays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of all logical displays indexed by logical display id.
|
* Map of all logical displays indexed by logical display id.
|
||||||
* Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache.
|
* Any modification to mLogicalDisplays must invalidate the DisplayManagerGlobal cache.
|
||||||
@@ -89,13 +109,16 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
private final DisplayDeviceRepository mDisplayDeviceRepo;
|
private final DisplayDeviceRepository mDisplayDeviceRepo;
|
||||||
private final DeviceStateToLayoutMap mDeviceStateToLayoutMap;
|
private final DeviceStateToLayoutMap mDeviceStateToLayoutMap;
|
||||||
private final Listener mListener;
|
private final Listener mListener;
|
||||||
|
private final DisplayManagerService.SyncRoot mSyncRoot;
|
||||||
|
private final LogicalDisplayMapperHandler mHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has an entry for every logical display that the rest of the system has been notified about.
|
* 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
|
* 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.
|
* is deleted or {@link LOGICAL_DISPLAY_EVENT_CHANGED} when it is changed. The values are any
|
||||||
|
* of the {@code UPDATE_STATE_*} constant types.
|
||||||
*/
|
*/
|
||||||
private final SparseBooleanArray mUpdatedLogicalDisplays = new SparseBooleanArray();
|
private final SparseIntArray mUpdatedLogicalDisplays = new SparseIntArray();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of all the display groups that we already told other people about. IOW, if a
|
* Keeps track of all the display groups that we already told other people about. IOW, if a
|
||||||
@@ -119,11 +142,18 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
|
private int mNextNonDefaultGroupId = Display.DEFAULT_DISPLAY_GROUP + 1;
|
||||||
private Layout mCurrentLayout = null;
|
private Layout mCurrentLayout = null;
|
||||||
private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
|
private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
|
||||||
|
private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
|
||||||
|
|
||||||
LogicalDisplayMapper(DisplayDeviceRepository repo, Listener listener) {
|
LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
|
||||||
|
@NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
|
||||||
|
@NonNull Handler handler) {
|
||||||
|
mSyncRoot = syncRoot;
|
||||||
|
mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
|
||||||
mDisplayDeviceRepo = repo;
|
mDisplayDeviceRepo = repo;
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
|
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
|
||||||
|
mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
|
||||||
|
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
|
||||||
mDisplayDeviceRepo.addListener(this);
|
mDisplayDeviceRepo.addListener(this);
|
||||||
mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
|
mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
|
||||||
}
|
}
|
||||||
@@ -142,6 +172,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
|
Slog.d(TAG, "Display device changed: " + device.getDisplayDeviceInfoLocked());
|
||||||
}
|
}
|
||||||
|
finishStateTransitionLocked(false /*force*/);
|
||||||
updateLogicalDisplaysLocked();
|
updateLogicalDisplaysLocked();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -166,7 +197,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
public LogicalDisplay getDisplayLocked(DisplayDevice device) {
|
public LogicalDisplay getDisplayLocked(DisplayDevice device) {
|
||||||
final int count = mLogicalDisplays.size();
|
final int count = mLogicalDisplays.size();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
LogicalDisplay display = mLogicalDisplays.valueAt(i);
|
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
|
||||||
if (display.getPrimaryDisplayDeviceLocked() == device) {
|
if (display.getPrimaryDisplayDeviceLocked() == device) {
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
@@ -198,6 +229,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
public int getDisplayGroupIdFromDisplayIdLocked(int displayId) {
|
public int getDisplayGroupIdFromDisplayIdLocked(int displayId) {
|
||||||
final LogicalDisplay display = getDisplayLocked(displayId);
|
final LogicalDisplay display = getDisplayLocked(displayId);
|
||||||
if (display == null) {
|
if (display == null) {
|
||||||
@@ -225,7 +257,6 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
ipw.increaseIndent();
|
ipw.increaseIndent();
|
||||||
|
|
||||||
ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
|
ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
|
||||||
|
|
||||||
ipw.println("mCurrentLayout=" + mCurrentLayout);
|
ipw.println("mCurrentLayout=" + mCurrentLayout);
|
||||||
|
|
||||||
final int logicalDisplayCount = mLogicalDisplays.size();
|
final int logicalDisplayCount = mLogicalDisplays.size();
|
||||||
@@ -244,19 +275,78 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setDeviceStateLocked(int state) {
|
void setDeviceStateLocked(int state) {
|
||||||
if (state != mDeviceState) {
|
Slog.i(TAG, "Requesting Transition to state: " + state);
|
||||||
resetLayoutLocked();
|
// As part of a state transition, we may need to turn off some displays temporarily so that
|
||||||
mDeviceState = state;
|
// the transition is smooth. Plus, on some devices, only one internal displays can be
|
||||||
applyLayoutLocked();
|
// on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be
|
||||||
updateLogicalDisplaysLocked();
|
// temporarily turned off.
|
||||||
|
if (mDeviceState != DeviceStateManager.INVALID_DEVICE_STATE) {
|
||||||
|
resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
|
||||||
|
}
|
||||||
|
mPendingDeviceState = state;
|
||||||
|
if (areAllTransitioningDisplaysOffLocked()) {
|
||||||
|
// Nothing to wait on, we're good to go
|
||||||
|
transitionToPendingStateLocked();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Postponing transition to state: " + mPendingDeviceState);
|
||||||
|
}
|
||||||
|
// Send the transitioning phase updates to DisplayManager so that the displays can
|
||||||
|
// start turning OFF in preparation for the new layout.
|
||||||
|
updateLogicalDisplaysLocked();
|
||||||
|
mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE,
|
||||||
|
TIMEOUT_STATE_TRANSITION_MILLIS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean areAllTransitioningDisplaysOffLocked() {
|
||||||
|
final int count = mLogicalDisplays.size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
final LogicalDisplay display = mLogicalDisplays.valueAt(i);
|
||||||
|
if (display.getPhase() != LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||||
|
if (device != null) {
|
||||||
|
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
||||||
|
if (info.state != Display.STATE_OFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transitionToPendingStateLocked() {
|
||||||
|
resetLayoutLocked(mDeviceState, mPendingDeviceState, LogicalDisplay.DISPLAY_PHASE_ENABLED);
|
||||||
|
mDeviceState = mPendingDeviceState;
|
||||||
|
mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
|
||||||
|
applyLayoutLocked();
|
||||||
|
updateLogicalDisplaysLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishStateTransitionLocked(boolean force) {
|
||||||
|
if (mPendingDeviceState == DeviceStateManager.INVALID_DEVICE_STATE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean displaysOff = areAllTransitioningDisplaysOffLocked();
|
||||||
|
if (displaysOff || force) {
|
||||||
|
transitionToPendingStateLocked();
|
||||||
|
mHandler.removeMessages(MSG_TRANSITION_TO_PENDING_DEVICE_STATE);
|
||||||
|
} else if (DEBUG) {
|
||||||
|
Slog.d(TAG, "Not yet ready to transition to state=" + mPendingDeviceState
|
||||||
|
+ " with displays-off=" + displaysOff + " and force=" + force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
|
private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
|
||||||
DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
|
DisplayDeviceInfo deviceInfo = device.getDisplayDeviceInfoLocked();
|
||||||
// Internal Displays need to have additional initialization.
|
// Internal Displays need to have additional initialization.
|
||||||
// TODO: b/168208162 - This initializes a default dynamic display layout for INTERNAL
|
// This initializes a default dynamic display layout for INTERNAL
|
||||||
// devices, which will eventually just be a fallback in case no static layout definitions
|
// devices, which is used as a fallback in case no static layout definitions
|
||||||
// exist or cannot be loaded.
|
// exist or cannot be loaded.
|
||||||
if (deviceInfo.type == Display.TYPE_INTERNAL) {
|
if (deviceInfo.type == Display.TYPE_INTERNAL) {
|
||||||
initializeInternalDisplayDeviceLocked(device);
|
initializeInternalDisplayDeviceLocked(device);
|
||||||
@@ -289,7 +379,8 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
|
|
||||||
display.updateLocked(mDisplayDeviceRepo);
|
display.updateLocked(mDisplayDeviceRepo);
|
||||||
final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
|
final DisplayInfo newDisplayInfo = display.getDisplayInfoLocked();
|
||||||
final boolean wasPreviouslyUpdated = mUpdatedLogicalDisplays.get(displayId);
|
final int updateState = mUpdatedLogicalDisplays.get(displayId, UPDATE_STATE_NEW);
|
||||||
|
final boolean wasPreviouslyUpdated = updateState != UPDATE_STATE_NEW;
|
||||||
|
|
||||||
// The display is no longer valid and needs to be removed.
|
// The display is no longer valid and needs to be removed.
|
||||||
if (!display.isValidLocked()) {
|
if (!display.isValidLocked()) {
|
||||||
@@ -331,6 +422,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
assignDisplayGroupLocked(display);
|
assignDisplayGroupLocked(display);
|
||||||
mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);
|
mLogicalDisplaysToUpdate.put(displayId, LOGICAL_DISPLAY_EVENT_CHANGED);
|
||||||
|
|
||||||
|
} else if (updateState == UPDATE_STATE_TRANSITION) {
|
||||||
|
mLogicalDisplaysToUpdate.put(displayId,
|
||||||
|
LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
|
||||||
|
|
||||||
// Display frame rate overrides changed.
|
// Display frame rate overrides changed.
|
||||||
} else if (!display.getPendingFrameRateOverrideUids().isEmpty()) {
|
} else if (!display.getPendingFrameRateOverrideUids().isEmpty()) {
|
||||||
mLogicalDisplaysToUpdate.put(
|
mLogicalDisplaysToUpdate.put(
|
||||||
@@ -347,7 +442,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mUpdatedLogicalDisplays.put(displayId, true);
|
mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_UPDATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go through the groups and do the same thing. We do this after displays since group
|
// Go through the groups and do the same thing. We do this after displays since group
|
||||||
@@ -376,12 +471,13 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
|
|
||||||
// Send the display and display group updates in order by message type. This is important
|
// 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.
|
// to ensure that addition and removal notifications happen in the right order.
|
||||||
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION);
|
||||||
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED);
|
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_ADDED);
|
||||||
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED);
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_REMOVED);
|
||||||
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED);
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_CHANGED);
|
||||||
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED);
|
||||||
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED);
|
|
||||||
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED);
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_SWAPPED);
|
||||||
|
sendUpdatesForDisplaysLocked(LOGICAL_DISPLAY_EVENT_ADDED);
|
||||||
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED);
|
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_CHANGED);
|
||||||
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_REMOVED);
|
sendUpdatesForGroupsLocked(DISPLAY_GROUP_EVENT_REMOVED);
|
||||||
|
|
||||||
@@ -400,7 +496,14 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int id = mLogicalDisplaysToUpdate.keyAt(i);
|
final int id = mLogicalDisplaysToUpdate.keyAt(i);
|
||||||
mListener.onLogicalDisplayEventLocked(getDisplayLocked(id), msg);
|
final LogicalDisplay display = getDisplayLocked(id);
|
||||||
|
if (DEBUG) {
|
||||||
|
final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
|
||||||
|
final String uniqueId = device == null ? "null" : device.getUniqueId();
|
||||||
|
Slog.d(TAG, "Sending " + displayEventToString(msg) + " for display=" + id
|
||||||
|
+ " with device=" + uniqueId);
|
||||||
|
}
|
||||||
|
mListener.onLogicalDisplayEventLocked(display, msg);
|
||||||
if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) {
|
if (msg == LOGICAL_DISPLAY_EVENT_REMOVED) {
|
||||||
// We wait until we sent the EVENT_REMOVED event before actually removing the
|
// We wait until we sent the EVENT_REMOVED event before actually removing the
|
||||||
// display.
|
// display.
|
||||||
@@ -464,36 +567,81 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the current layout in preparation for a new layout. Layouts can specify if some
|
* Goes through all the displays used in the layouts for the specified {@code fromState} and
|
||||||
* displays should be disabled (OFF). When switching from one layout to another, we go
|
* {@code toState} and applies the specified {@code phase}. When a new layout is requested, we
|
||||||
* through each of the displays and make sure any displays we might have disabled are
|
* put the displays that will change into a transitional phase so that they can all be turned
|
||||||
* enabled again.
|
* OFF. Once all are confirmed OFF, then this method gets called again to reset the phase to
|
||||||
|
* normal operation. This helps to ensure that all display-OFF requests are made before
|
||||||
|
* display-ON which in turn hides any resizing-jank windows might incur when switching displays.
|
||||||
|
*
|
||||||
|
* @param fromState The state we are switching from.
|
||||||
|
* @param toState The state we are switching to.
|
||||||
|
* @param phase The new phase to apply to the displays.
|
||||||
*/
|
*/
|
||||||
private void resetLayoutLocked() {
|
private void resetLayoutLocked(int fromState, int toState, @DisplayPhase int phase) {
|
||||||
final Layout layout = mDeviceStateToLayoutMap.get(mDeviceState);
|
final Layout fromLayout = mDeviceStateToLayoutMap.get(fromState);
|
||||||
for (int i = layout.size() - 1; i >= 0; i--) {
|
final Layout toLayout = mDeviceStateToLayoutMap.get(toState);
|
||||||
final Layout.Display displayLayout = layout.getAt(i);
|
|
||||||
final LogicalDisplay display = getDisplayLocked(displayLayout.getLogicalDisplayId());
|
final int count = mLogicalDisplays.size();
|
||||||
if (display != null) {
|
for (int i = 0; i < count; i++) {
|
||||||
enableDisplayLocked(display, true); // Reset all displays back to enabled
|
final LogicalDisplay logicalDisplay = mLogicalDisplays.valueAt(i);
|
||||||
|
final int displayId = logicalDisplay.getDisplayIdLocked();
|
||||||
|
final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked();
|
||||||
|
if (device == null) {
|
||||||
|
// If there's no device, then the logical display is due to be removed. Ignore it.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the display associations this display-device has in the old layout and the
|
||||||
|
// new layout.
|
||||||
|
final DisplayAddress address = device.getDisplayDeviceInfoLocked().address;
|
||||||
|
|
||||||
|
// Virtual displays do not have addresses.
|
||||||
|
final Layout.Display fromDisplay =
|
||||||
|
address != null ? fromLayout.getByAddress(address) : null;
|
||||||
|
final Layout.Display toDisplay =
|
||||||
|
address != null ? toLayout.getByAddress(address) : null;
|
||||||
|
|
||||||
|
// If a layout doesn't mention a display-device at all, then the display-device defaults
|
||||||
|
// to enabled. This is why we treat null as "enabled" in the code below.
|
||||||
|
final boolean wasEnabled = fromDisplay == null || fromDisplay.isEnabled();
|
||||||
|
final boolean willBeEnabled = toDisplay == null || toDisplay.isEnabled();
|
||||||
|
|
||||||
|
final boolean deviceHasNewLogicalDisplayId = fromDisplay != null && toDisplay != null
|
||||||
|
&& fromDisplay.getLogicalDisplayId() != toDisplay.getLogicalDisplayId();
|
||||||
|
|
||||||
|
// We consider a display-device as changing/transition if
|
||||||
|
// 1) It's already marked as transitioning
|
||||||
|
// 2) It's going from enabled to disabled
|
||||||
|
// 3) It's enabled, but it's mapped to a new logical display ID. To the user this
|
||||||
|
// would look like apps moving from one screen to another since task-stacks stay
|
||||||
|
// with the logical display [ID].
|
||||||
|
final boolean isTransitioning =
|
||||||
|
(logicalDisplay.getPhase() == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION)
|
||||||
|
|| (wasEnabled && !willBeEnabled)
|
||||||
|
|| (wasEnabled && deviceHasNewLogicalDisplayId);
|
||||||
|
|
||||||
|
if (isTransitioning) {
|
||||||
|
setDisplayPhase(logicalDisplay, phase);
|
||||||
|
if (phase == LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION) {
|
||||||
|
mUpdatedLogicalDisplays.put(displayId, UPDATE_STATE_TRANSITION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply (or reapply) the currently selected display layout.
|
* Apply (or reapply) the currently selected display layout.
|
||||||
*/
|
*/
|
||||||
private void applyLayoutLocked() {
|
private void applyLayoutLocked() {
|
||||||
final Layout layout = mDeviceStateToLayoutMap.get(mDeviceState);
|
final Layout oldLayout = mCurrentLayout;
|
||||||
mCurrentLayout = layout;
|
mCurrentLayout = mDeviceStateToLayoutMap.get(mDeviceState);
|
||||||
Slog.i(TAG, "Applying the display layout for device state(" + mDeviceState
|
Slog.i(TAG, "Applying layout: " + mCurrentLayout + ", Previous layout: " + oldLayout);
|
||||||
+ "): " + layout);
|
|
||||||
|
|
||||||
// Go through each of the displays in the current layout set.
|
// Go through each of the displays in the current layout set.
|
||||||
final int size = layout.size();
|
final int size = mCurrentLayout.size();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
final Layout.Display displayLayout = layout.getAt(i);
|
final Layout.Display displayLayout = mCurrentLayout.getAt(i);
|
||||||
|
|
||||||
// If the underlying display-device we want to use for this display
|
// 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
|
// doesn't exist, then skip it. This can happen at startup as display-devices
|
||||||
@@ -521,8 +669,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
if (newDisplay != oldDisplay) {
|
if (newDisplay != oldDisplay) {
|
||||||
newDisplay.swapDisplaysLocked(oldDisplay);
|
newDisplay.swapDisplaysLocked(oldDisplay);
|
||||||
}
|
}
|
||||||
enableDisplayLocked(newDisplay, displayLayout.isEnabled());
|
|
||||||
|
if (!displayLayout.isEnabled()) {
|
||||||
|
setDisplayPhase(newDisplay, LogicalDisplay.DISPLAY_PHASE_DISABLED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -540,23 +692,23 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
|
final LogicalDisplay display = new LogicalDisplay(displayId, layerStack, device);
|
||||||
display.updateLocked(mDisplayDeviceRepo);
|
display.updateLocked(mDisplayDeviceRepo);
|
||||||
mLogicalDisplays.put(displayId, display);
|
mLogicalDisplays.put(displayId, display);
|
||||||
enableDisplayLocked(display, device != null);
|
setDisplayPhase(display, LogicalDisplay.DISPLAY_PHASE_ENABLED);
|
||||||
return display;
|
return display;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableDisplayLocked(LogicalDisplay display, boolean isEnabled) {
|
private void setDisplayPhase(LogicalDisplay display, @DisplayPhase int phase) {
|
||||||
final int displayId = display.getDisplayIdLocked();
|
final int displayId = display.getDisplayIdLocked();
|
||||||
final DisplayInfo info = display.getDisplayInfoLocked();
|
final DisplayInfo info = display.getDisplayInfoLocked();
|
||||||
|
|
||||||
final boolean disallowSecondaryDisplay = mSingleDisplayDemoMode
|
final boolean disallowSecondaryDisplay = mSingleDisplayDemoMode
|
||||||
&& (info.type != Display.TYPE_INTERNAL);
|
&& (info.type != Display.TYPE_INTERNAL);
|
||||||
if (isEnabled && disallowSecondaryDisplay) {
|
if (phase != LogicalDisplay.DISPLAY_PHASE_DISABLED && disallowSecondaryDisplay) {
|
||||||
Slog.i(TAG, "Not creating a logical display for a secondary display because single"
|
Slog.i(TAG, "Not creating a logical display for a secondary display because single"
|
||||||
+ " display demo mode is enabled: " + display.getDisplayInfoLocked());
|
+ " display demo mode is enabled: " + display.getDisplayInfoLocked());
|
||||||
isEnabled = false;
|
phase = LogicalDisplay.DISPLAY_PHASE_DISABLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
display.setEnabled(isEnabled);
|
display.setPhase(phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int assignDisplayGroupIdLocked(boolean isOwnDisplayGroup) {
|
private int assignDisplayGroupIdLocked(boolean isOwnDisplayGroup) {
|
||||||
@@ -564,14 +716,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeInternalDisplayDeviceLocked(DisplayDevice device) {
|
private void initializeInternalDisplayDeviceLocked(DisplayDevice device) {
|
||||||
// We always want to make sure that our default display layout creates a logical
|
// We always want to make sure that our default layout creates a logical
|
||||||
// display for every internal display device that is found.
|
// 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
|
// 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.
|
// the default layout definition if it is not already there.
|
||||||
final Layout layoutSet = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT);
|
final Layout layout = mDeviceStateToLayoutMap.get(DeviceStateToLayoutMap.STATE_DEFAULT);
|
||||||
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
|
||||||
final boolean isDefault = (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
|
final boolean isDefault = (info.flags & DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY) != 0;
|
||||||
layoutSet.createDisplayLocked(info.address, isDefault, true /* isEnabled */);
|
final boolean isEnabled = isDefault || mSupportsConcurrentInternalDisplays;
|
||||||
|
layout.createDisplayLocked(info.address, isDefault, isEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int assignLayerStackLocked(int displayId) {
|
private int assignLayerStackLocked(int displayId) {
|
||||||
@@ -580,9 +733,45 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
|
|||||||
return displayId;
|
return displayId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String displayEventToString(int msg) {
|
||||||
|
switch(msg) {
|
||||||
|
case LOGICAL_DISPLAY_EVENT_ADDED:
|
||||||
|
return "added";
|
||||||
|
case LOGICAL_DISPLAY_EVENT_DEVICE_STATE_TRANSITION:
|
||||||
|
return "transition";
|
||||||
|
case LOGICAL_DISPLAY_EVENT_CHANGED:
|
||||||
|
return "changed";
|
||||||
|
case LOGICAL_DISPLAY_EVENT_FRAME_RATE_OVERRIDES_CHANGED:
|
||||||
|
return "framerate_override";
|
||||||
|
case LOGICAL_DISPLAY_EVENT_SWAPPED:
|
||||||
|
return "swapped";
|
||||||
|
case LOGICAL_DISPLAY_EVENT_REMOVED:
|
||||||
|
return "removed";
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onLogicalDisplayEventLocked(LogicalDisplay display, int event);
|
void onLogicalDisplayEventLocked(LogicalDisplay display, int event);
|
||||||
void onDisplayGroupEventLocked(int groupId, int event);
|
void onDisplayGroupEventLocked(int groupId, int event);
|
||||||
void onTraversalRequested();
|
void onTraversalRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class LogicalDisplayMapperHandler extends Handler {
|
||||||
|
LogicalDisplayMapperHandler(Looper looper) {
|
||||||
|
super(looper, null, true /*async*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case MSG_TRANSITION_TO_PENDING_DEVICE_STATE:
|
||||||
|
synchronized (mSyncRoot) {
|
||||||
|
finishStateTransitionLocked(true /*force*/);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.server.display.layout;
|
|||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.DisplayAddress;
|
import android.view.DisplayAddress;
|
||||||
|
|
||||||
@@ -100,11 +101,28 @@ public class Layout {
|
|||||||
*
|
*
|
||||||
* @return The display corresponding to the specified display ID.
|
* @return The display corresponding to the specified display ID.
|
||||||
*/
|
*/
|
||||||
|
@Nullable
|
||||||
public Display getById(int id) {
|
public Display getById(int id) {
|
||||||
for (int i = 0; i < mDisplays.size(); i++) {
|
for (int i = 0; i < mDisplays.size(); i++) {
|
||||||
Display layout = mDisplays.get(i);
|
Display display = mDisplays.get(i);
|
||||||
if (id == layout.getLogicalDisplayId()) {
|
if (id == display.getLogicalDisplayId()) {
|
||||||
return layout;
|
return display;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param address The display address to check.
|
||||||
|
*
|
||||||
|
* @return The display corresponding to the specified address.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public Display getByAddress(@NonNull DisplayAddress address) {
|
||||||
|
for (int i = 0; i < mDisplays.size(); i++) {
|
||||||
|
Display display = mDisplays.get(i);
|
||||||
|
if (address.equals(display.getAddress())) {
|
||||||
|
return display;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -27,17 +27,20 @@ import static org.junit.Assert.assertNotEquals;
|
|||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.clearInvocations;
|
import static org.mockito.Mockito.clearInvocations;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.PropertyInvalidatedCache;
|
import android.app.PropertyInvalidatedCache;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
import android.os.test.TestLooper;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayAddress;
|
import android.view.DisplayAddress;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
@@ -61,9 +64,12 @@ public class LogicalDisplayMapperTest {
|
|||||||
|
|
||||||
private DisplayDeviceRepository mDisplayDeviceRepo;
|
private DisplayDeviceRepository mDisplayDeviceRepo;
|
||||||
private LogicalDisplayMapper mLogicalDisplayMapper;
|
private LogicalDisplayMapper mLogicalDisplayMapper;
|
||||||
private Context mContext;
|
private TestLooper mLooper;
|
||||||
|
private Handler mHandler;
|
||||||
|
|
||||||
@Mock LogicalDisplayMapper.Listener mListenerMock;
|
@Mock LogicalDisplayMapper.Listener mListenerMock;
|
||||||
|
@Mock Context mContextMock;
|
||||||
|
@Mock Resources mResourcesMock;
|
||||||
|
|
||||||
@Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
|
@Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
|
||||||
|
|
||||||
@@ -73,7 +79,6 @@ public class LogicalDisplayMapperTest {
|
|||||||
System.setProperty("dexmaker.share_classloader", "true");
|
System.setProperty("dexmaker.share_classloader", "true");
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
mContext = InstrumentationRegistry.getContext();
|
|
||||||
mDisplayDeviceRepo = new DisplayDeviceRepository(
|
mDisplayDeviceRepo = new DisplayDeviceRepository(
|
||||||
new DisplayManagerService.SyncRoot(),
|
new DisplayManagerService.SyncRoot(),
|
||||||
new PersistentDataStore(new PersistentDataStore.Injector() {
|
new PersistentDataStore(new PersistentDataStore.Injector() {
|
||||||
@@ -94,7 +99,15 @@ public class LogicalDisplayMapperTest {
|
|||||||
// Disable binder caches in this process.
|
// Disable binder caches in this process.
|
||||||
PropertyInvalidatedCache.disableForTestMode();
|
PropertyInvalidatedCache.disableForTestMode();
|
||||||
|
|
||||||
mLogicalDisplayMapper = new LogicalDisplayMapper(mDisplayDeviceRepo, mListenerMock);
|
when(mContextMock.getResources()).thenReturn(mResourcesMock);
|
||||||
|
when(mResourcesMock.getBoolean(
|
||||||
|
com.android.internal.R.bool.config_supportsConcurrentInternalDisplays))
|
||||||
|
.thenReturn(true);
|
||||||
|
|
||||||
|
mLooper = new TestLooper();
|
||||||
|
mHandler = new Handler(mLooper.getLooper());
|
||||||
|
mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mDisplayDeviceRepo,
|
||||||
|
mListenerMock, new DisplayManagerService.SyncRoot(), mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -299,7 +312,7 @@ public class LogicalDisplayMapperTest {
|
|||||||
private DisplayDeviceInfo mSentInfo;
|
private DisplayDeviceInfo mSentInfo;
|
||||||
|
|
||||||
TestDisplayDevice() {
|
TestDisplayDevice() {
|
||||||
super(null, null, "test_display_" + sUniqueTestDisplayId++, mContext);
|
super(null, null, "test_display_" + sUniqueTestDisplayId++, mContextMock);
|
||||||
mInfo = new DisplayDeviceInfo();
|
mInfo = new DisplayDeviceInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user