summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java6
-rw-r--r--core/res/res/values/config.xml9
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceRepository.java11
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java40
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerShellCommand.java26
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java47
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java145
-rw-r--r--services/core/java/com/android/server/policy/DisplayFoldController.java2
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java8
10 files changed, 281 insertions, 14 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index defcab7c3035..a86c5cbd2451 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -267,6 +267,12 @@ public abstract class DisplayManagerInternal {
public abstract void ignoreProximitySensorUntilChanged();
/**
+ * Sets the folded state of the device.
+ * TODO: b/168208522 - Remove in favor of DisplayStatePolicy when that is available.
+ */
+ public abstract void setDeviceFolded(boolean isFolded);
+
+ /**
* Describes the requested power state of the display.
*
* This object is intended to describe the general characteristics of the
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a334be301a46..c4d096320607 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4443,4 +4443,13 @@
<!-- WindowsManager JetPack display features -->
<string name="config_display_features" translatable="false" />
+
+ <!-- Physical Display IDs of the display-devices that are swapped when a folding device folds.
+ This list is expected to contain two elements: the first is the display to use
+ when the device is folded, the second is the display to use when unfolded. If the array
+ is empty or the display IDs are not recognized, this feature is turned off and the value
+ ignored.
+ TODO: b/170470621 - remove once we can have multiple Internal displays in DMS as
+ well as a notification from DisplayStateManager. -->
+ <string-array name="config_internalFoldedPhysicalDisplayIds" translatable="false" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 54101e6b369f..9858f5e7c585 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4076,4 +4076,5 @@
<java-symbol type="array" name="config_keep_warming_services" />
<java-symbol type="string" name="config_display_features" />
+ <java-symbol type="array" name="config_internalFoldedPhysicalDisplayIds" />
</resources>
diff --git a/services/core/java/com/android/server/display/DisplayDeviceRepository.java b/services/core/java/com/android/server/display/DisplayDeviceRepository.java
index aa4db29e0d49..5c0fceb9b795 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceRepository.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceRepository.java
@@ -112,6 +112,17 @@ class DisplayDeviceRepository implements DisplayAdapter.Listener {
}
}
+ public DisplayDevice getByIdLocked(@NonNull String uniqueId) {
+ final int count = mDisplayDevices.size();
+ for (int i = 0; i < count; i++) {
+ final DisplayDevice d = mDisplayDevices.get(i);
+ if (uniqueId.equals(d.getUniqueId())) {
+ return d;
+ }
+ }
+ return null;
+ }
+
private void handleDisplayDeviceAdded(DisplayDevice device) {
synchronized (mSyncRoot) {
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index ffce3be4b769..a600292eca31 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -324,7 +324,7 @@ public final class DisplayManagerService extends SystemService {
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
- mLogicalDisplayMapper = new LogicalDisplayMapper(mDisplayDeviceRepo,
+ mLogicalDisplayMapper = new LogicalDisplayMapper(context, mDisplayDeviceRepo,
new LogicalDisplayListener(), mPersistentDataStore);
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
Resources resources = mContext.getResources();
@@ -576,6 +576,7 @@ public final class DisplayManagerService extends SystemService {
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestGlobalDisplayState("
+ Display.stateToString(state)
+ ", brightness=" + brightnessState + ")");
+
mGlobalDisplayState = state;
mGlobalDisplayBrightness = brightnessState;
applyGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
@@ -983,6 +984,15 @@ public final class DisplayManagerService extends SystemService {
scheduleTraversalLocked(false);
}
+ private void handleLogicalDisplaySwappedLocked(@NonNull LogicalDisplay display) {
+ final DisplayDevice device = display.getPrimaryDisplayDeviceLocked();
+ final Runnable work = updateDisplayStateLocked(device);
+ if (work != null) {
+ mHandler.post(work);
+ }
+ handleLogicalDisplayChangedLocked(display);
+ }
+
private void applyGlobalDisplayStateLocked(List<Runnable> workQueue) {
mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
Runnable runnable = updateDisplayStateLocked(device);
@@ -997,10 +1007,15 @@ public final class DisplayManagerService extends SystemService {
// by the display power controller (if known).
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
- // TODO - multi-display - The rules regarding what display state to apply to each
+ // TODO - b/170498827 The rules regarding what display state to apply to each
// display will depend on the configuration/mapping of logical displays.
- return device.requestDisplayStateLocked(
- mGlobalDisplayState, mGlobalDisplayBrightness);
+ // Clean up LogicalDisplay.isEnabled() mechanism once this is fixed.
+ int state = mGlobalDisplayState;
+ final LogicalDisplay display = mLogicalDisplayMapper.getLocked(device);
+ if (display != null && !display.isEnabled()) {
+ state = Display.STATE_OFF;
+ }
+ return device.requestDisplayStateLocked(state, mGlobalDisplayBrightness);
}
return null;
}
@@ -1346,6 +1361,12 @@ public final class DisplayManagerService extends SystemService {
}
}
+ void setFoldOverride(Boolean isFolded) {
+ synchronized (mSyncRoot) {
+ mLogicalDisplayMapper.setFoldOverrideLocked(isFolded);
+ }
+ }
+
private void clearViewportsLocked() {
mViewports.clear();
}
@@ -1698,6 +1719,10 @@ public final class DisplayManagerService extends SystemService {
case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED:
handleLogicalDisplayRemovedLocked(display);
break;
+
+ case LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_SWAPPED:
+ handleLogicalDisplaySwappedLocked(display);
+ break;
}
}
@@ -2538,6 +2563,13 @@ public final class DisplayManagerService extends SystemService {
public void ignoreProximitySensorUntilChanged() {
mDisplayPowerController.ignoreProximitySensorUntilChanged();
}
+
+ @Override
+ public void setDeviceFolded(boolean isFolded) {
+ synchronized (mSyncRoot) {
+ mLogicalDisplayMapper.setDeviceFoldedLocked(isFolded);
+ }
+ }
}
class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
index 0c6c797b917a..111664a078df 100644
--- a/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
+++ b/services/core/java/com/android/server/display/DisplayManagerShellCommand.java
@@ -56,6 +56,8 @@ class DisplayManagerShellCommand extends ShellCommand {
return setDisplayWhiteBalanceLoggingEnabled(false);
case "dwb-set-cct":
return setAmbientColorTemperatureOverride();
+ case "set-fold":
+ return setFoldOverride();
default:
return handleDefaultCommands(cmd);
}
@@ -82,6 +84,8 @@ class DisplayManagerShellCommand extends ShellCommand {
pw.println(" Disable display white-balance logging.");
pw.println(" dwb-set-cct CCT");
pw.println(" Sets the ambient color temperature override to CCT (use -1 to disable).");
+ pw.println(" set-fold [fold|unfold|reset]");
+ pw.println(" Simulates the 'fold' state of a device. 'reset' for default behavior.");
pw.println();
Intent.printIntentArgsHelp(pw , "");
}
@@ -148,4 +152,26 @@ class DisplayManagerShellCommand extends ShellCommand {
mService.setAmbientColorTemperatureOverride(cct);
return 0;
}
+
+ private int setFoldOverride() {
+ String state = getNextArg();
+ if (state == null) {
+ getErrPrintWriter().println("Error: no parameter specified for set-fold");
+ return 1;
+ }
+ final Boolean isFolded;
+ if ("fold".equals(state)) {
+ isFolded = true;
+ } else if ("unfold".equals(state)) {
+ isFolded = false;
+ } else if ("reset".equals(state)) {
+ isFolded = null;
+ } else {
+ getErrPrintWriter().println("Error: Invalid fold state request: " + state);
+ return 1;
+ }
+
+ mService.setFoldOverride(isFolded);
+ return 0;
+ }
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index bf8b891cffb8..a17a294cd1d7 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -16,9 +16,11 @@
package com.android.server.display;
+import android.annotation.NonNull;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerInternal;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -57,6 +59,7 @@ import java.util.Objects;
* </p>
*/
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
@@ -114,6 +117,12 @@ final class LogicalDisplay {
private final Rect mTempLayerStackRect = new Rect();
private final Rect mTempDisplayRect = new Rect();
+ /**
+ * Indicates that the Logical display is enabled (default). See {@link #setEnabled} for
+ * more information.
+ */
+ private boolean mIsEnabled = true;
+
public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
mDisplayId = displayId;
mLayerStack = layerStack;
@@ -575,6 +584,44 @@ final class LogicalDisplay {
mDisplayScalingDisabled = disableScaling;
}
+ /**
+ * Swap the underlying {@link DisplayDevice} with the specificed LogicalDisplay.
+ *
+ * @param targetDisplay The display with which to swap display-devices.
+ * @return {@code true} if the displays were swapped, {@code false} otherwise.
+ */
+ 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;
+ }
+
+ final DisplayDevice tmpDevice = mPrimaryDisplayDevice;
+ mPrimaryDisplayDevice = targetDisplay.mPrimaryDisplayDevice;
+ targetDisplay.mPrimaryDisplayDevice = tmpDevice;
+ return true;
+ }
+
+ /**
+ * Sets the LogicalDisplay to be enabled or disabled. If the display is not enabled,
+ * 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}
+ * if disabled indicating that the display has been forced to be OFF.
+ */
+ public boolean isEnabled() {
+ return mIsEnabled;
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println("mDisplayId=" + mDisplayId);
pw.println("mLayerStack=" + mLayerStack);
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 8a90a142a765..942a12ebf64e 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -16,7 +16,9 @@
package com.android.server.display;
+import android.content.Context;
import android.os.SystemProperties;
+import android.text.TextUtils;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -26,6 +28,7 @@ import com.android.internal.util.IndentingPrintWriter;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.Objects;
import java.util.function.Consumer;
/**
@@ -39,9 +42,12 @@ import java.util.function.Consumer;
class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private static final String TAG = "LogicalDisplayMapper";
+ private static final boolean DEBUG = false;
+
public static final int LOGICAL_DISPLAY_EVENT_ADDED = 1;
public static final int LOGICAL_DISPLAY_EVENT_CHANGED = 2;
public static final int LOGICAL_DISPLAY_EVENT_REMOVED = 3;
+ public static final int LOGICAL_DISPLAY_EVENT_SWAPPED = 4;
/**
* Temporary display info, used for comparing display configurations.
@@ -59,6 +65,24 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final boolean mSingleDisplayDemoMode;
/**
+ * Physical Display ID of the DisplayDevice to associate with the default LogicalDisplay
+ * when {@link mIsFolded} is set to {@code true}.
+ */
+ private String mDisplayIdToUseWhenFolded;
+
+ /**
+ * Physical Display ID of the DisplayDevice to associate with the default LogicalDisplay
+ * when {@link mIsFolded} is set to {@code false}.
+ */
+ private String mDisplayIdToUseWhenUnfolded;
+
+ /** Overrides the folded state of the device. For use with ADB commands. */
+ private Boolean mIsFoldedOverride;
+
+ /** Saves the last device fold state. */
+ private boolean mIsFolded;
+
+ /**
* 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?
@@ -71,13 +95,15 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
private final PersistentDataStore mPersistentDataStore;
private final Listener mListener;
- LogicalDisplayMapper(DisplayDeviceRepository repo, Listener listener,
+ LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener,
PersistentDataStore persistentDataStore) {
mDisplayDeviceRepo = repo;
mPersistentDataStore = persistentDataStore;
mListener = listener;
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
mDisplayDeviceRepo.addListener(this);
+
+ loadFoldedDisplayConfig(context);
}
@Override
@@ -141,23 +167,104 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
}
+ public void setDeviceFoldedLocked(boolean isFolded) {
+ mIsFolded = isFolded;
+ if (mIsFoldedOverride != null) {
+ isFolded = mIsFoldedOverride.booleanValue();
+ }
+
+ if (mDisplayIdToUseWhenFolded == null || mDisplayIdToUseWhenUnfolded == null
+ || mLogicalDisplays.size() < 2) {
+ // Do nothing if this behavior is disabled or there are less than two displays.
+ return;
+ }
+
+ final DisplayDevice deviceFolded =
+ mDisplayDeviceRepo.getByIdLocked(mDisplayIdToUseWhenFolded);
+ final DisplayDevice deviceUnfolded =
+ mDisplayDeviceRepo.getByIdLocked(mDisplayIdToUseWhenUnfolded);
+ if (deviceFolded == null || deviceUnfolded == null) {
+ // If the expected devices for folding functionality are not present, return early.
+ return;
+ }
+
+ // Find the associated LogicalDisplays for the configured "folding" DeviceDisplays.
+ final LogicalDisplay displayFolded = getLocked(deviceFolded);
+ final LogicalDisplay displayUnfolded = getLocked(deviceUnfolded);
+ if (displayFolded == null || displayFolded == null) {
+ // If the expected displays are not present, return early.
+ return;
+ }
+
+ // Find out which display is currently default and which is disabled.
+ final LogicalDisplay defaultDisplay = mLogicalDisplays.get(Display.DEFAULT_DISPLAY);
+ final LogicalDisplay disabledDisplay;
+ if (defaultDisplay == displayFolded) {
+ disabledDisplay = displayUnfolded;
+ } else if (defaultDisplay == displayUnfolded) {
+ disabledDisplay = displayFolded;
+ } else {
+ // If neither folded or unfolded displays are currently set to the default display, we
+ // are in an unknown state and it's best to log the error and bail.
+ Slog.e(TAG, "Unexpected: when attempting to swap displays, neither of the two"
+ + " configured displays were set up as the default display. Default: "
+ + defaultDisplay.getDisplayInfoLocked() + ", ConfiguredDisplays: [ folded="
+ + displayFolded.getDisplayInfoLocked() + ", unfolded="
+ + displayUnfolded.getDisplayInfoLocked() + " ]");
+ return;
+ }
+
+ if (isFolded == (defaultDisplay == displayFolded)) {
+ // Nothing to do, already in the right state.
+ return;
+ }
+
+ // Everything was checked and we need to swap, lets swap.
+ displayFolded.swapDisplaysLocked(displayUnfolded);
+
+ // 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);
+ disabledDisplay.setEnabled(false);
+
+ // Update the world
+ updateLogicalDisplaysLocked();
+
+ if (DEBUG) {
+ Slog.d(TAG, "Folded displays: isFolded: " + isFolded + ", defaultDisplay? "
+ + defaultDisplay.getDisplayInfoLocked());
+ }
+ }
+
public void dumpLocked(PrintWriter pw) {
pw.println("LogicalDisplayMapper:");
- pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
- pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.increaseIndent();
+
+ ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
+ ipw.println("mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
final int logicalDisplayCount = mLogicalDisplays.size();
- pw.println();
- pw.println(" Logical Displays: size=" + logicalDisplayCount);
+ ipw.println();
+ ipw.println("Logical Displays: size=" + logicalDisplayCount);
- IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
- ipw.increaseIndent();
for (int i = 0; i < logicalDisplayCount; i++) {
int displayId = mLogicalDisplays.keyAt(i);
LogicalDisplay display = mLogicalDisplays.valueAt(i);
- pw.println(" Display " + displayId + ":");
+ ipw.println("Display " + displayId + ":");
+ ipw.increaseIndent();
display.dumpLocked(ipw);
+ ipw.decreaseIndent();
+ ipw.println();
+ }
+ }
+
+ void setFoldOverrideLocked(Boolean isFolded) {
+ if (!Objects.equals(isFolded, mIsFoldedOverride)) {
+ mIsFoldedOverride = isFolded;
+ setDeviceFoldedLocked(mIsFolded);
}
}
@@ -211,8 +318,11 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
mListener.onLogicalDisplayEventLocked(display,
LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED);
} else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
- mListener.onLogicalDisplayEventLocked(display,
- LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_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 {
// 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
@@ -236,6 +346,21 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
return displayId;
}
+ private void loadFoldedDisplayConfig(Context context) {
+ final String[] displayIds = context.getResources().getStringArray(
+ com.android.internal.R.array.config_internalFoldedPhysicalDisplayIds);
+
+ if (displayIds.length != 2 || TextUtils.isEmpty(displayIds[0])
+ || TextUtils.isEmpty(displayIds[1])) {
+ Slog.w(TAG, "Folded display configuration invalid: [" + Arrays.toString(displayIds)
+ + "]");
+ return;
+ }
+
+ mDisplayIdToUseWhenFolded = displayIds[0];
+ mDisplayIdToUseWhenUnfolded = displayIds[1];
+ }
+
public interface Listener {
void onLogicalDisplayEventLocked(LogicalDisplay display, int event);
void onTraversalRequested();
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index 0db3d78fed5b..0ca6e5923f1b 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -80,6 +80,8 @@ class DisplayFoldController {
}
void setDeviceFolded(boolean folded) {
+ mDisplayManagerInternal.setDeviceFolded(folded);
+
if (mFolded != null && mFolded == folded) {
return;
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 0313aaeef0d6..b74de1347224 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -117,6 +117,7 @@ import android.database.ContentObserver;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
import android.hardware.hdmi.HdmiAudioSystemClient;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
@@ -366,6 +367,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
StatusBarManagerInternal mStatusBarManagerInternal;
AudioManagerInternal mAudioManagerInternal;
DisplayManager mDisplayManager;
+ DisplayManagerInternal mDisplayManagerInternal;
boolean mPreloadedRecentApps;
final Object mServiceAquireLock = new Object();
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
@@ -469,6 +471,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
private boolean mLidControlsDisplayFold;
+ private boolean mShouldSwapDisplaysOnLidSwitch;
int mShortPressOnPowerBehavior;
int mLongPressOnPowerBehavior;
int mVeryLongPressOnPowerBehavior;
@@ -1752,6 +1755,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mDisplayManager = mContext.getSystemService(DisplayManager.class);
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mPackageManager = mContext.getPackageManager();
mHasFeatureWatch = mPackageManager.hasSystemFeature(FEATURE_WATCH);
mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
@@ -1845,6 +1849,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.integer.config_lidNavigationAccessibility);
mLidControlsDisplayFold = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_lidControlsDisplayFold);
+ mShouldSwapDisplaysOnLidSwitch = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_internalFoldedPhysicalDisplayIds).length == 2;
mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
@@ -5035,6 +5041,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int lidState = mDefaultDisplayPolicy.getLidState();
if (mLidControlsDisplayFold && mDisplayFoldController != null) {
mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
+ } else if (mShouldSwapDisplaysOnLidSwitch) {
+ mDisplayManagerInternal.setDeviceFolded(lidState == LID_CLOSED);
} else if (lidState == LID_CLOSED) {
int lidBehavior = getLidBehavior();
switch (lidBehavior) {