Skip to content

Commit 9b4125e

Browse files
committed
Screen magnifier should handle window rebuilds correctly.
1. The way for computing the magnified region was simplistic and incorrect. It was ignoring window layering resulting in broken behavior. For example, if the IME is up, then the everything else is magnifed and the IME not. Now the keyguard appears and covers the IME but the magnified region does not expand while it would since the keyguard completely covers the not magnified IME window. bug:7138937 Change-Id: I21414635aefab700ce75d40f3e913c1472cba202
1 parent ee6c6ae commit 9b4125e

File tree

3 files changed

+99
-18
lines changed

3 files changed

+99
-18
lines changed

core/java/android/view/WindowInfo.java

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,15 @@ public class WindowInfo implements Parcelable {
4545

4646
public final Rect touchableRegion = new Rect();
4747

48-
public int type;
48+
public int type = UNDEFINED;
4949

50-
public float compatibilityScale;
50+
public float compatibilityScale = UNDEFINED;
5151

5252
public boolean visible;
5353

54-
public int displayId;
54+
public int displayId = UNDEFINED;
55+
56+
public int layer = UNDEFINED;
5557

5658
private WindowInfo() {
5759
/* do nothing - reduce visibility */
@@ -71,6 +73,7 @@ public void writeToParcel(Parcel parcel, int flags) {
7173
parcel.writeFloat(compatibilityScale);
7274
parcel.writeInt(visible ? 1 : 0);
7375
parcel.writeInt(displayId);
76+
parcel.writeInt(layer);
7477
recycle();
7578
}
7679

@@ -82,6 +85,7 @@ private void initFromParcel(Parcel parcel) {
8285
compatibilityScale = parcel.readFloat();
8386
visible = (parcel.readInt() == 1);
8487
displayId = parcel.readInt();
88+
layer = parcel.readInt();
8589
}
8690

8791
public static WindowInfo obtain(WindowInfo other) {
@@ -90,9 +94,10 @@ public static WindowInfo obtain(WindowInfo other) {
9094
info.frame.set(other.frame);
9195
info.touchableRegion.set(other.touchableRegion);
9296
info.type = other.type;
93-
info.displayId = other.displayId;
9497
info.compatibilityScale = other.compatibilityScale;
9598
info.visible = other.visible;
99+
info.displayId = other.displayId;
100+
info.layer = other.layer;
96101
return info;
97102
}
98103

@@ -131,8 +136,25 @@ private void clear() {
131136
frame.setEmpty();
132137
touchableRegion.setEmpty();
133138
type = UNDEFINED;
134-
displayId = UNDEFINED;
139+
compatibilityScale = UNDEFINED;
135140
visible = false;
141+
displayId = UNDEFINED;
142+
layer = UNDEFINED;
143+
}
144+
145+
@Override
146+
public String toString() {
147+
StringBuilder builder = new StringBuilder();
148+
builder.append("Window [token:").append((token != null) ? token.hashCode() : null);
149+
builder.append(", displayId:").append(displayId);
150+
builder.append(", type:").append(type);
151+
builder.append(", visible:").append(visible);
152+
builder.append(", layer:").append(layer);
153+
builder.append(", compatibilityScale:").append(compatibilityScale);
154+
builder.append(", frame:").append(frame);
155+
builder.append(", touchableRegion:").append(touchableRegion);
156+
builder.append("]");
157+
return builder.toString();
136158
}
137159

138160
/**

services/java/com/android/server/accessibility/ScreenMagnifier.java

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@
6767
import com.android.internal.os.SomeArgs;
6868

6969
import java.util.ArrayList;
70+
import java.util.Collections;
71+
import java.util.Comparator;
7072

7173
/**
7274
* This class handles the screen magnification when accessibility is enabled.
@@ -1020,7 +1022,9 @@ private void handleOnWindowTransition(int transition, WindowInfo info) {
10201022
}
10211023
if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
10221024
|| info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
1023-
|| info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG) {
1025+
|| info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG
1026+
|| info.type == WindowManager.LayoutParams.TYPE_KEYGUARD
1027+
|| info.type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
10241028
switch (transition) {
10251029
case WindowManagerPolicy.TRANSIT_ENTER:
10261030
case WindowManagerPolicy.TRANSIT_SHOW:
@@ -1473,7 +1477,9 @@ private static final class Viewport {
14731477

14741478
private final ArrayList<WindowInfo> mTempWindowInfoList = new ArrayList<WindowInfo>();
14751479

1476-
private final Rect mTempRect = new Rect();
1480+
private final Rect mTempRect1 = new Rect();
1481+
private final Rect mTempRect2 = new Rect();
1482+
private final Rect mTempRect3 = new Rect();
14771483

14781484
private final IWindowManager mWindowManagerService;
14791485
private final DisplayProvider mDisplayProvider;
@@ -1542,31 +1548,83 @@ public Rect evaluate(float fraction, Rect fromFrame, Rect toFrame) {
15421548
recomputeBounds(false);
15431549
}
15441550

1551+
private final Comparator<WindowInfo> mWindowInfoInverseComparator =
1552+
new Comparator<WindowInfo>() {
1553+
@Override
1554+
public int compare(WindowInfo lhs, WindowInfo rhs) {
1555+
if (lhs.layer != rhs.layer) {
1556+
return rhs.layer - lhs.layer;
1557+
}
1558+
if (lhs.touchableRegion.top != rhs.touchableRegion.top) {
1559+
return rhs.touchableRegion.top - lhs.touchableRegion.top;
1560+
}
1561+
if (lhs.touchableRegion.left != rhs.touchableRegion.left) {
1562+
return rhs.touchableRegion.left - lhs.touchableRegion.left;
1563+
}
1564+
if (lhs.touchableRegion.right != rhs.touchableRegion.right) {
1565+
return rhs.touchableRegion.right - lhs.touchableRegion.right;
1566+
}
1567+
if (lhs.touchableRegion.bottom != rhs.touchableRegion.bottom) {
1568+
return rhs.touchableRegion.bottom - lhs.touchableRegion.bottom;
1569+
}
1570+
return 0;
1571+
}
1572+
};
1573+
15451574
public void recomputeBounds(boolean animate) {
1546-
Rect frame = mTempRect;
1547-
frame.set(0, 0, mDisplayProvider.getDisplayInfo().logicalWidth,
1548-
mDisplayProvider.getDisplayInfo().logicalHeight);
1575+
Rect magnifiedFrame = mTempRect1;
1576+
magnifiedFrame.set(0, 0, 0, 0);
1577+
1578+
Rect notMagnifiedFrame = mTempRect2;
1579+
notMagnifiedFrame.set(0, 0, 0, 0);
1580+
15491581
ArrayList<WindowInfo> infos = mTempWindowInfoList;
15501582
infos.clear();
1583+
int windowCount = 0;
15511584
try {
15521585
mWindowManagerService.getVisibleWindowsForDisplay(
15531586
mDisplayProvider.getDisplay().getDisplayId(), infos);
1554-
final int windowCount = infos.size();
1587+
Collections.sort(infos, mWindowInfoInverseComparator);
1588+
windowCount = infos.size();
15551589
for (int i = 0; i < windowCount; i++) {
15561590
WindowInfo info = infos.get(i);
1557-
if (info.type == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
1558-
|| info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
1559-
|| info.type == WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG) {
1560-
subtract(frame, info.touchableRegion);
1591+
if (info.type == WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY) {
1592+
continue;
1593+
}
1594+
if (isWindowMagnified(info.type)) {
1595+
Rect clippedFrame = mTempRect3;
1596+
clippedFrame.set(info.touchableRegion);
1597+
subtract(clippedFrame, notMagnifiedFrame);
1598+
magnifiedFrame.union(clippedFrame);
1599+
} else {
1600+
Rect clippedFrame = mTempRect3;
1601+
clippedFrame.set(info.touchableRegion);
1602+
subtract(clippedFrame, magnifiedFrame);
1603+
notMagnifiedFrame.union(clippedFrame);
1604+
}
1605+
if (magnifiedFrame.bottom >= notMagnifiedFrame.top) {
1606+
break;
15611607
}
1562-
info.recycle();
15631608
}
15641609
} catch (RemoteException re) {
15651610
/* ignore */
15661611
} finally {
1567-
infos.clear();
1612+
for (int i = windowCount - 1; i >= 0; i--) {
1613+
infos.remove(i).recycle();
1614+
}
15681615
}
1569-
resize(frame, animate);
1616+
1617+
final int displayWidth = mDisplayProvider.getDisplayInfo().logicalWidth;
1618+
final int displayHeight = mDisplayProvider.getDisplayInfo().logicalHeight;
1619+
magnifiedFrame.intersect(0, 0, displayWidth, displayHeight);
1620+
1621+
resize(magnifiedFrame, animate);
1622+
}
1623+
1624+
private boolean isWindowMagnified(int type) {
1625+
return (type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
1626+
&& type != WindowManager.LayoutParams.TYPE_INPUT_METHOD
1627+
&& type != WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
15701628
}
15711629

15721630
public void rotationChanged() {

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,7 @@ private WindowInfo getWindowInfoForWindowStateLocked(WindowState window) {
31533153
info.compatibilityScale = window.mGlobalScale;
31543154
info.visible = window.isVisibleLw()
31553155
|| info.type == WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
3156+
info.layer = window.mLayer;
31563157
window.getTouchableRegion(mTempRegion);
31573158
mTempRegion.getBounds(info.touchableRegion);
31583159
return info;

0 commit comments

Comments
 (0)