Skip to content

Commit 27f1d67

Browse files
author
Jeff Brown
committed
Add special mirroring modes for demonstration purposes.
Assume rotation of HDMI display is portait. $ adb shell setprop persist.demo.hdmirotation portrait Don't lock rotation while HDMI is plugged in. $ adb shell setprop persist.demo.hdmirotationlock false Hide secondary displays from apps but continue mirroring to them. $ adb shell setprop persist.demo.singledisplay true Bug: 7326281 Change-Id: I8f9a3b0bc19821a3a01043b0f516806dac82ce53
1 parent a7f9c96 commit 27f1d67

File tree

5 files changed

+70
-12
lines changed

5 files changed

+70
-12
lines changed

policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
299299
int mCarDockRotation;
300300
int mDeskDockRotation;
301301
int mHdmiRotation;
302+
boolean mHdmiRotationLock;
302303

303304
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
304305
int mUserRotation = Surface.ROTATION_0;
@@ -1035,11 +1036,14 @@ public void setInitialDisplaySize(Display display, int width, int height, int de
10351036
mCanHideNavigationBar = false;
10361037
}
10371038

1039+
// For demo purposes, allow the rotation of the HDMI display to be controlled.
1040+
// By default, HDMI locks rotation to landscape.
10381041
if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
10391042
mHdmiRotation = mPortraitRotation;
10401043
} else {
10411044
mHdmiRotation = mLandscapeRotation;
10421045
}
1046+
mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true);
10431047
}
10441048

10451049
public void updateSettings() {
@@ -3873,7 +3877,7 @@ public int rotationForOrientationLw(int orientation, int lastRotation) {
38733877
// enable 180 degree rotation while docked.
38743878
preferredRotation = mDeskDockEnablesAccelerometer
38753879
? sensorRotation : mDeskDockRotation;
3876-
} else if (mHdmiPlugged) {
3880+
} else if (mHdmiPlugged && mHdmiRotationLock) {
38773881
// Ignore sensor when plugged into HDMI.
38783882
// Note that the dock orientation overrides the HDMI orientation.
38793883
preferredRotation = mHdmiRotation;
@@ -4538,5 +4542,7 @@ public void dump(String prefix, PrintWriter pw, String[] args) {
45384542
pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
45394543
pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
45404544
pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
4545+
pw.print(prefix); pw.print("mHdmiRotation="); pw.print(mHdmiRotation);
4546+
pw.print(" mHdmiRotationLock="); pw.println(mHdmiRotationLock);
45414547
}
45424548
}

services/java/com/android/server/display/DisplayDeviceInfo.java

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.android.server.display;
1818

1919
import android.util.DisplayMetrics;
20+
import android.view.Surface;
2021

2122
import libcore.util.Objects;
2223

@@ -31,11 +32,21 @@ final class DisplayDeviceInfo {
3132
public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
3233

3334
/**
34-
* Flag: Indicates that this display device can rotate to show contents in a
35-
* different orientation. Otherwise the rotation is assumed to be fixed in the
36-
* natural orientation and the display manager should transform the content to fit.
35+
* Flag: Indicates that the orientation of this display device is coupled to the
36+
* rotation of its associated logical display.
37+
* <p>
38+
* This flag should be applied to the default display to indicate that the user
39+
* physically rotates the display when content is presented in a different orientation.
40+
* The display manager will apply a coordinate transformation assuming that the
41+
* physical orientation of the display matches the logical orientation of its content.
42+
* </p><p>
43+
* The flag should not be set when the display device is mounted in a fixed orientation
44+
* such as on a desk. The display manager will apply a coordinate transformation
45+
* such as a scale and translation to letterbox or pillarbox format under the
46+
* assumption that the physical orientation of the display is invariant.
47+
* </p>
3748
*/
38-
public static final int FLAG_SUPPORTS_ROTATION = 1 << 1;
49+
public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
3950

4051
/**
4152
* Flag: Indicates that this display device has secure video output, such as HDCP.
@@ -116,6 +127,17 @@ final class DisplayDeviceInfo {
116127
*/
117128
public int touch;
118129

130+
/**
131+
* The additional rotation to apply to all content presented on the display device
132+
* relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}.
133+
* <p>
134+
* This field can be used to compensate for the fact that the display has been
135+
* physically rotated relative to its natural orientation such as an HDMI monitor
136+
* that has been mounted sideways to appear to be portrait rather than landscape.
137+
* </p>
138+
*/
139+
public int rotation = Surface.ROTATION_0;
140+
119141
public void setAssumedDensityForExternalDisplay(int width, int height) {
120142
densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
121143
// Technically, these values should be smaller than the apparent density
@@ -139,7 +161,8 @@ public boolean equals(DisplayDeviceInfo other) {
139161
&& xDpi == other.xDpi
140162
&& yDpi == other.yDpi
141163
&& flags == other.flags
142-
&& touch == other.touch;
164+
&& touch == other.touch
165+
&& rotation == other.rotation;
143166
}
144167

145168
@Override
@@ -157,14 +180,18 @@ public void copyFrom(DisplayDeviceInfo other) {
157180
yDpi = other.yDpi;
158181
flags = other.flags;
159182
touch = other.touch;
183+
rotation = other.rotation;
160184
}
161185

162186
// For debugging purposes
163187
@Override
164188
public String toString() {
165-
return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
189+
return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", "
190+
+ refreshRate + " fps, "
166191
+ "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
167-
+ ", touch " + touchToString(touch) + flagsToString(flags) + "}";
192+
+ ", touch " + touchToString(touch) + flagsToString(flags)
193+
+ ", rotation " + rotation
194+
+ "}";
168195
}
169196

170197
private static String touchToString(int touch) {
@@ -185,8 +212,8 @@ private static String flagsToString(int flags) {
185212
if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
186213
msg.append(", FLAG_DEFAULT_DISPLAY");
187214
}
188-
if ((flags & FLAG_SUPPORTS_ROTATION) != 0) {
189-
msg.append(", FLAG_SUPPORTS_ROTATION");
215+
if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
216+
msg.append(", FLAG_ROTATES_WITH_CONTENT");
190217
}
191218
if ((flags & FLAG_SECURE) != 0) {
192219
msg.append(", FLAG_SECURE");

services/java/com/android/server/display/DisplayManagerService.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
127127
// services should be started. This option may disable certain display adapters.
128128
public boolean mOnlyCore;
129129

130+
// True if the display manager service should pretend there is only one display
131+
// and only tell applications about the existence of the default logical display.
132+
// The display manager can still mirror content to secondary displays but applications
133+
// cannot present unique content on those displays.
134+
// Used for demonstration purposes only.
135+
private final boolean mSingleDisplayDemoMode;
136+
130137
// All callback records indexed by calling process id.
131138
public final SparseArray<CallbackRecord> mCallbacks =
132139
new SparseArray<CallbackRecord>();
@@ -182,6 +189,7 @@ public DisplayManagerService(Context context, Handler mainHandler, Handler uiHan
182189
mHandler = new DisplayManagerHandler(mainHandler.getLooper());
183190
mUiHandler = uiHandler;
184191
mDisplayAdapterListener = new DisplayAdapterListener();
192+
mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
185193

186194
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);
187195
}
@@ -631,6 +639,12 @@ private void addLogicalDisplayLocked(DisplayDevice device) {
631639
isDefault = false;
632640
}
633641

642+
if (!isDefault && mSingleDisplayDemoMode) {
643+
Slog.i(TAG, "Not creating a logical display for a secondary display "
644+
+ " because single display demo mode is enabled: " + deviceInfo);
645+
return;
646+
}
647+
634648
final int displayId = assignDisplayIdLocked(isDefault);
635649
final int layerStack = assignLayerStackLocked(displayId);
636650

@@ -857,6 +871,7 @@ public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
857871
pw.println(" mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
858872
pw.println(" mDefaultViewport=" + mDefaultViewport);
859873
pw.println(" mExternalTouchViewport=" + mExternalTouchViewport);
874+
pw.println(" mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
860875

861876
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
862877
ipw.increaseIndent();

services/java/com/android/server/display/LocalDisplayAdapter.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import android.os.Handler;
2121
import android.os.IBinder;
2222
import android.os.Looper;
23+
import android.os.SystemProperties;
2324
import android.util.SparseArray;
2425
import android.view.DisplayEventReceiver;
2526
import android.view.Surface;
@@ -135,7 +136,7 @@ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
135136
mInfo.name = getContext().getResources().getString(
136137
com.android.internal.R.string.display_manager_built_in_display_name);
137138
mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
138-
| DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION;
139+
| DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
139140
mInfo.densityDpi = (int)(mPhys.density * 160 + 0.5f);
140141
mInfo.xDpi = mPhys.xDpi;
141142
mInfo.yDpi = mPhys.yDpi;
@@ -145,6 +146,12 @@ public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
145146
com.android.internal.R.string.display_manager_hdmi_display_name);
146147
mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
147148
mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
149+
150+
// For demonstration purposes, allow rotation of the external display.
151+
// In the future we might allow the user to configure this directly.
152+
if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
153+
mInfo.rotation = Surface.ROTATION_270;
154+
}
148155
}
149156
}
150157
return mInfo;

services/java/com/android/server/display/LogicalDisplay.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,13 @@ public void configureDisplayInTransactionLocked(DisplayDevice device,
241241
// is rotated when the contents of the logical display are rendered.
242242
int orientation = Surface.ROTATION_0;
243243
if (device == mPrimaryDisplayDevice
244-
&& (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_ROTATION) != 0) {
244+
&& (displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
245245
orientation = displayInfo.rotation;
246246
}
247247

248+
// Apply the physical rotation of the display device itself.
249+
orientation = (orientation + displayDeviceInfo.rotation) % 4;
250+
248251
// Set the frame.
249252
// The frame specifies the rotated physical coordinates into which the viewport
250253
// is mapped. We need to take care to preserve the aspect ratio of the viewport.

0 commit comments

Comments
 (0)