Skip to content

Commit 4ed8fe7

Browse files
author
Jeff Brown
committed
More improvements to the display manager.
Added more complete support for logical displays with support for mirroring, rotation and scaling. Improved the overlay display adapter's touch interactions. A big change here is that the display manager no longer relies on a single-threaded model to maintain its synchronization invariants. Unfortunately we had to change this so as to play nice with the fact that the window manager wants to own the surface flinger transaction around display and surface manipulations. As a result, the display manager has to be able to update displays from the context of any thread. It would be nice to make this process more cooperative. There are already several components competing to perform surface flinger transactions including the window manager, display manager, electron beam, overlay display window, and mouse pointer. They are not manipulating the same surfaces but they can collide with one another when they make global changes to the displays. Change-Id: I04f448594241f2004f6f3d1a81ccd12c566bf296
1 parent a492c3a commit 4ed8fe7

24 files changed

+1733
-789
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23473,6 +23473,7 @@ package android.view {
2347323473
method public int getDisplayId();
2347423474
method public deprecated int getHeight();
2347523475
method public void getMetrics(android.util.DisplayMetrics);
23476+
method public java.lang.String getName();
2347623477
method public deprecated int getOrientation();
2347723478
method public deprecated int getPixelFormat();
2347823479
method public void getRealMetrics(android.util.DisplayMetrics);

core/java/android/hardware/display/DisplayManagerGlobal.java

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ public final class DisplayManagerGlobal {
4242
private static final String TAG = "DisplayManager";
4343
private static final boolean DEBUG = false;
4444

45+
// True if display info and display ids should be cached.
46+
//
47+
// FIXME: The cache is currently disabled because it's unclear whether we have the
48+
// necessary guarantees that the caches will always be flushed before clients
49+
// attempt to observe their new state. For example, depending on the order
50+
// in which the binder transactions take place, we might have a problem where
51+
// an application could start processing a configuration change due to a display
52+
// orientation change before the display info cache has actually been invalidated.
53+
private static final boolean USE_CACHE = false;
54+
4555
public static final int EVENT_DISPLAY_ADDED = 1;
4656
public static final int EVENT_DISPLAY_CHANGED = 2;
4757
public static final int EVENT_DISPLAY_REMOVED = 3;
@@ -91,21 +101,27 @@ public static DisplayManagerGlobal getInstance() {
91101
public DisplayInfo getDisplayInfo(int displayId) {
92102
try {
93103
synchronized (mLock) {
94-
DisplayInfo info = mDisplayInfoCache.get(displayId);
95-
if (info != null) {
96-
return info;
104+
DisplayInfo info;
105+
if (USE_CACHE) {
106+
info = mDisplayInfoCache.get(displayId);
107+
if (info != null) {
108+
return info;
109+
}
97110
}
98111

99112
info = mDm.getDisplayInfo(displayId);
100113
if (info == null) {
101114
return null;
102115
}
116+
117+
if (USE_CACHE) {
118+
mDisplayInfoCache.put(displayId, info);
119+
}
120+
registerCallbackIfNeededLocked();
121+
103122
if (DEBUG) {
104123
Log.d(TAG, "getDisplayInfo: displayId=" + displayId + ", info=" + info);
105124
}
106-
107-
mDisplayInfoCache.put(displayId, info);
108-
registerCallbackIfNeededLocked();
109125
return info;
110126
}
111127
} catch (RemoteException ex) {
@@ -122,11 +138,18 @@ public DisplayInfo getDisplayInfo(int displayId) {
122138
public int[] getDisplayIds() {
123139
try {
124140
synchronized (mLock) {
125-
if (mDisplayIdCache == null) {
126-
mDisplayIdCache = mDm.getDisplayIds();
127-
registerCallbackIfNeededLocked();
141+
if (USE_CACHE) {
142+
if (mDisplayIdCache != null) {
143+
return mDisplayIdCache;
144+
}
145+
}
146+
147+
int[] displayIds = mDm.getDisplayIds();
148+
if (USE_CACHE) {
149+
mDisplayIdCache = displayIds;
128150
}
129-
return mDisplayIdCache;
151+
registerCallbackIfNeededLocked();
152+
return displayIds;
130153
}
131154
} catch (RemoteException ex) {
132155
Log.e(TAG, "Could not get display ids from display manager.", ex);
@@ -215,10 +238,12 @@ private void registerCallbackIfNeededLocked() {
215238

216239
private void handleDisplayEvent(int displayId, int event) {
217240
synchronized (mLock) {
218-
mDisplayInfoCache.remove(displayId);
241+
if (USE_CACHE) {
242+
mDisplayInfoCache.remove(displayId);
219243

220-
if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
221-
mDisplayIdCache = null;
244+
if (event == EVENT_DISPLAY_ADDED || event == EVENT_DISPLAY_REMOVED) {
245+
mDisplayIdCache = null;
246+
}
222247
}
223248

224249
final int numListeners = mDisplayListeners.size();

core/java/android/os/Handler.java

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,12 @@ public final boolean postAtFrontOfQueue(Runnable r)
431431
* set up a Handler thread and need to perform some initialization steps on
432432
* it before continuing execution.
433433
*
434+
* If timeout occurs then this method returns <code>false</code> but the runnable
435+
* will remain posted on the handler and may already be in progress or
436+
* complete at a later time.
437+
*
434438
* @param r The Runnable that will be executed synchronously.
439+
* @param timeout The timeout in milliseconds, or 0 to wait indefinitely.
435440
*
436441
* @return Returns true if the Runnable was successfully executed.
437442
* Returns false on failure, usually because the
@@ -441,18 +446,21 @@ public final boolean postAtFrontOfQueue(Runnable r)
441446
* If we ever do make it part of the API, we might want to rename it to something
442447
* less funny like runUnsafe().
443448
*/
444-
public final boolean runWithScissors(final Runnable r) {
449+
public final boolean runWithScissors(final Runnable r, long timeout) {
445450
if (r == null) {
446451
throw new IllegalArgumentException("runnable must not be null");
447452
}
453+
if (timeout < 0) {
454+
throw new IllegalArgumentException("timeout must be non-negative");
455+
}
448456

449457
if (Looper.myLooper() == mLooper) {
450458
r.run();
451459
return true;
452460
}
453461

454462
BlockingRunnable br = new BlockingRunnable(r);
455-
return br.postAndWait(this);
463+
return br.postAndWait(this, timeout);
456464
}
457465

458466
/**
@@ -743,16 +751,30 @@ public void run() {
743751
}
744752
}
745753

746-
public boolean postAndWait(Handler handler) {
754+
public boolean postAndWait(Handler handler, long timeout) {
747755
if (!handler.post(this)) {
748756
return false;
749757
}
750758

751759
synchronized (this) {
752-
while (!mDone) {
753-
try {
754-
wait();
755-
} catch (InterruptedException ex) {
760+
if (timeout > 0) {
761+
final long expirationTime = SystemClock.uptimeMillis() + timeout;
762+
while (!mDone) {
763+
long delay = expirationTime - SystemClock.uptimeMillis();
764+
if (delay <= 0) {
765+
return false; // timeout
766+
}
767+
try {
768+
wait(delay);
769+
} catch (InterruptedException ex) {
770+
}
771+
}
772+
} else {
773+
while (!mDone) {
774+
try {
775+
wait();
776+
} catch (InterruptedException ex) {
777+
}
756778
}
757779
}
758780
}

core/java/android/view/Display.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public final class Display {
5353

5454
private final DisplayManagerGlobal mGlobal;
5555
private final int mDisplayId;
56+
private final int mLayerStack;
57+
private final String mName;
5658
private final CompatibilityInfoHolder mCompatibilityInfo;
5759

5860
private DisplayInfo mDisplayInfo; // never null
@@ -90,6 +92,8 @@ public Display(DisplayManagerGlobal global,
9092
mGlobal = global;
9193
mDisplayId = displayId;
9294
mDisplayInfo = displayInfo;
95+
mLayerStack = displayInfo.layerStack; // can never change as long as the display is valid
96+
mName = displayInfo.name; // cannot change as long as the display is valid
9397
mCompatibilityInfo = compatibilityInfo;
9498
mIsValid = true;
9599
}
@@ -146,13 +150,11 @@ public boolean getDisplayInfo(DisplayInfo outDisplayInfo) {
146150
* Each display has its own independent layer stack upon which surfaces
147151
* are placed to be managed by surface flinger.
148152
*
149-
* @return The layer stack number.
153+
* @return The display's layer stack number.
150154
* @hide
151155
*/
152156
public int getLayerStack() {
153-
// Note: This is the current convention but there is no requirement that
154-
// the display id and layer stack id be the same.
155-
return mDisplayId;
157+
return mLayerStack;
156158
}
157159

158160
/**
@@ -165,6 +167,14 @@ public CompatibilityInfoHolder getCompatibilityInfo() {
165167
return mCompatibilityInfo;
166168
}
167169

170+
/**
171+
* Gets the name of the display.
172+
* @return The display's name.
173+
*/
174+
public String getName() {
175+
return mName;
176+
}
177+
168178
/**
169179
* Gets the size of the display, in pixels.
170180
* <p>

core/java/android/view/DisplayInfo.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,23 @@
2121
import android.os.Parcelable;
2222
import android.util.DisplayMetrics;
2323

24+
import libcore.util.Objects;
25+
2426
/**
2527
* Describes the characteristics of a particular logical display.
2628
* @hide
2729
*/
2830
public final class DisplayInfo implements Parcelable {
31+
/**
32+
* The surface flinger layer stack associated with this logical display.
33+
*/
34+
public int layerStack;
35+
36+
/**
37+
* The human-readable name of the display.
38+
*/
39+
public String name;
40+
2941
/**
3042
* The width of the portion of the display that is available to applications, in pixels.
3143
* Represents the size of the display minus any system decorations.
@@ -147,11 +159,37 @@ private DisplayInfo(Parcel source) {
147159
}
148160

149161
@Override
150-
public int describeContents() {
151-
return 0;
162+
public boolean equals(Object o) {
163+
return o instanceof DisplayInfo && equals((DisplayInfo)o);
164+
}
165+
166+
public boolean equals(DisplayInfo other) {
167+
return other != null
168+
&& layerStack == other.layerStack
169+
&& Objects.equal(name, other.name)
170+
&& appWidth == other.appWidth
171+
&& appHeight == other.appHeight
172+
&& smallestNominalAppWidth == other.smallestNominalAppWidth
173+
&& smallestNominalAppHeight == other.smallestNominalAppHeight
174+
&& largestNominalAppWidth == other.largestNominalAppWidth
175+
&& largestNominalAppHeight == other.largestNominalAppHeight
176+
&& logicalWidth == other.logicalWidth
177+
&& logicalHeight == other.logicalHeight
178+
&& rotation == other.rotation
179+
&& refreshRate == other.refreshRate
180+
&& logicalDensityDpi == other.logicalDensityDpi
181+
&& physicalXDpi == other.physicalXDpi
182+
&& physicalYDpi == other.physicalYDpi;
183+
}
184+
185+
@Override
186+
public int hashCode() {
187+
return 0; // don't care
152188
}
153189

154190
public void copyFrom(DisplayInfo other) {
191+
layerStack = other.layerStack;
192+
name = other.name;
155193
appWidth = other.appWidth;
156194
appHeight = other.appHeight;
157195
smallestNominalAppWidth = other.smallestNominalAppWidth;
@@ -168,6 +206,8 @@ public void copyFrom(DisplayInfo other) {
168206
}
169207

170208
public void readFromParcel(Parcel source) {
209+
layerStack = source.readInt();
210+
name = source.readString();
171211
appWidth = source.readInt();
172212
appHeight = source.readInt();
173213
smallestNominalAppWidth = source.readInt();
@@ -185,6 +225,8 @@ public void readFromParcel(Parcel source) {
185225

186226
@Override
187227
public void writeToParcel(Parcel dest, int flags) {
228+
dest.writeInt(layerStack);
229+
dest.writeString(name);
188230
dest.writeInt(appWidth);
189231
dest.writeInt(appHeight);
190232
dest.writeInt(smallestNominalAppWidth);
@@ -200,6 +242,11 @@ public void writeToParcel(Parcel dest, int flags) {
200242
dest.writeFloat(physicalYDpi);
201243
}
202244

245+
@Override
246+
public int describeContents() {
247+
return 0;
248+
}
249+
203250
public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) {
204251
getMetricsWithSize(outMetrics, cih, appWidth, appHeight);
205252
}
@@ -231,13 +278,14 @@ private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHold
231278
// For debugging purposes
232279
@Override
233280
public String toString() {
234-
return "app " + appWidth + " x " + appHeight
281+
return "DisplayInfo{\"" + name + "\", app " + appWidth + " x " + appHeight
235282
+ ", real " + logicalWidth + " x " + logicalHeight
236283
+ ", largest app " + largestNominalAppWidth + " x " + largestNominalAppHeight
237284
+ ", smallest app " + smallestNominalAppWidth + " x " + smallestNominalAppHeight
238285
+ ", " + refreshRate + " fps"
239286
+ ", rotation " + rotation
240287
+ ", density " + logicalDensityDpi
241-
+ ", " + physicalXDpi + " x " + physicalYDpi + " dpi";
288+
+ ", " + physicalXDpi + " x " + physicalYDpi + " dpi"
289+
+ ", layerStack " + layerStack + "}";
242290
}
243291
}

core/java/android/view/Surface.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,17 +743,59 @@ public OutOfResourcesException(String name) {
743743
}
744744

745745
/**
746-
* Describes the properties of a physical display.
746+
* Describes the properties of a physical display known to surface flinger.
747747
* @hide
748748
*/
749749
public static final class PhysicalDisplayInfo {
750-
// TODO: redesign this
751750
public int width;
752751
public int height;
753752
public float refreshRate;
754753
public float density;
755754
public float xDpi;
756755
public float yDpi;
756+
757+
public PhysicalDisplayInfo() {
758+
}
759+
760+
public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
761+
copyFrom(other);
762+
}
763+
764+
@Override
765+
public boolean equals(Object o) {
766+
return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
767+
}
768+
769+
public boolean equals(PhysicalDisplayInfo other) {
770+
return other != null
771+
&& width == other.width
772+
&& height == other.height
773+
&& refreshRate == other.refreshRate
774+
&& density == other.density
775+
&& xDpi == other.xDpi
776+
&& yDpi == other.yDpi;
777+
}
778+
779+
@Override
780+
public int hashCode() {
781+
return 0; // don't care
782+
}
783+
784+
public void copyFrom(PhysicalDisplayInfo other) {
785+
width = other.width;
786+
height = other.height;
787+
refreshRate = other.refreshRate;
788+
density = other.density;
789+
xDpi = other.xDpi;
790+
yDpi = other.yDpi;
791+
}
792+
793+
// For debugging purposes
794+
@Override
795+
public String toString() {
796+
return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
797+
+ "density " + density + ", " + xDpi + " x " + yDpi + " dpi}";
798+
}
757799
}
758800

759801
/**

0 commit comments

Comments
 (0)