Merge "Refine getTransformationMatrix for windows in a re-parented display" into qt-dev
This commit is contained in:
@@ -317,7 +317,7 @@ public class ActivityView extends ViewGroup {
|
||||
* regions and avoid focus switches by touches on this view.
|
||||
*/
|
||||
public void onLocationChanged() {
|
||||
updateTapExcludeRegion();
|
||||
updateLocationAndTapExcludeRegion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -329,37 +329,50 @@ public class ActivityView extends ViewGroup {
|
||||
public boolean gatherTransparentRegion(Region region) {
|
||||
// The tap exclude region may be affected by any view on top of it, so we detect the
|
||||
// possible change by monitoring this function.
|
||||
updateTapExcludeRegion();
|
||||
updateLocationAndTapExcludeRegion();
|
||||
return super.gatherTransparentRegion(region);
|
||||
}
|
||||
|
||||
/** Compute and send current tap exclude region to WM for this view. */
|
||||
private void updateTapExcludeRegion() {
|
||||
if (!isAttachedToWindow()) {
|
||||
/**
|
||||
* Sends current location in window and tap exclude region to WM for this view.
|
||||
*/
|
||||
private void updateLocationAndTapExcludeRegion() {
|
||||
if (mVirtualDisplay == null || !isAttachedToWindow()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int x = mLocationInWindow[0];
|
||||
int y = mLocationInWindow[1];
|
||||
getLocationInWindow(mLocationInWindow);
|
||||
if (x != mLocationInWindow[0] || y != mLocationInWindow[1]) {
|
||||
x = mLocationInWindow[0];
|
||||
y = mLocationInWindow[1];
|
||||
WindowManagerGlobal.getWindowSession().updateDisplayContentLocation(
|
||||
getWindow(), x, y, mVirtualDisplay.getDisplay().getDisplayId());
|
||||
}
|
||||
updateTapExcludeRegion(x, y);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowAsRuntimeException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Computes and sends current tap exclude region to WM for this view. */
|
||||
private void updateTapExcludeRegion(int x, int y) throws RemoteException {
|
||||
if (!canReceivePointerEvents()) {
|
||||
cleanTapExcludeRegion();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
getLocationInWindow(mLocationInWindow);
|
||||
final int x = mLocationInWindow[0];
|
||||
final int y = mLocationInWindow[1];
|
||||
mTapExcludeRegion.set(x, y, x + getWidth(), y + getHeight());
|
||||
mTapExcludeRegion.set(x, y, x + getWidth(), y + getHeight());
|
||||
|
||||
// There might be views on top of us. We need to subtract those areas from the tap
|
||||
// exclude region.
|
||||
final ViewParent parent = getParent();
|
||||
if (parent instanceof ViewGroup) {
|
||||
((ViewGroup) parent).subtractObscuredTouchableRegion(mTapExcludeRegion, this);
|
||||
}
|
||||
|
||||
WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
|
||||
mTapExcludeRegion);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowAsRuntimeException();
|
||||
// There might be views on top of us. We need to subtract those areas from the tap
|
||||
// exclude region.
|
||||
final ViewParent parent = getParent();
|
||||
if (parent != null) {
|
||||
parent.subtractObscuredTouchableRegion(mTapExcludeRegion, this);
|
||||
}
|
||||
|
||||
WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
|
||||
mTapExcludeRegion);
|
||||
}
|
||||
|
||||
private class SurfaceCallback implements SurfaceHolder.Callback {
|
||||
@@ -379,7 +392,7 @@ public class ActivityView extends ViewGroup {
|
||||
mVirtualDisplay.setDisplayState(true);
|
||||
}
|
||||
|
||||
updateTapExcludeRegion();
|
||||
updateLocationAndTapExcludeRegion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -387,7 +400,7 @@ public class ActivityView extends ViewGroup {
|
||||
if (mVirtualDisplay != null) {
|
||||
mVirtualDisplay.resize(width, height, getBaseDisplayDensity());
|
||||
}
|
||||
updateTapExcludeRegion();
|
||||
updateLocationAndTapExcludeRegion();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -471,7 +484,8 @@ public class ActivityView extends ViewGroup {
|
||||
|
||||
try {
|
||||
// TODO: Find a way to consolidate these calls to the server.
|
||||
wm.reparentDisplayContent(displayId, mRootSurfaceControl);
|
||||
WindowManagerGlobal.getWindowSession().reparentDisplayContent(
|
||||
getWindow(), mRootSurfaceControl, displayId);
|
||||
wm.dontOverrideDisplayInfo(displayId);
|
||||
if (mSingleTaskInstance) {
|
||||
mActivityTaskManager.setDisplayToSingleTaskInstance(displayId);
|
||||
|
||||
@@ -621,18 +621,6 @@ interface IWindowManager
|
||||
*/
|
||||
void setShouldShowIme(int displayId, boolean shouldShow);
|
||||
|
||||
/**
|
||||
* Reparent the top layers for a display to the requested surfaceControl. The display that
|
||||
* is going to be re-parented (the displayId passed in) needs to have been created by the same
|
||||
* process that is requesting the re-parent. This is to ensure clients can't just re-parent
|
||||
* display content info to any SurfaceControl, as this would be a security issue.
|
||||
*
|
||||
* @param displayId The id of the display.
|
||||
* @param surfaceControlHandle The SurfaceControl that the top level layers for the
|
||||
* display should be re-parented to.
|
||||
*/
|
||||
void reparentDisplayContent(int displayId, in SurfaceControl sc);
|
||||
|
||||
/**
|
||||
* Waits for transactions to get applied before injecting input.
|
||||
* This includes waiting for the input windows to get sent to InputManager.
|
||||
|
||||
@@ -256,6 +256,31 @@ interface IWindowSession {
|
||||
|
||||
void updatePointerIcon(IWindow window);
|
||||
|
||||
/**
|
||||
* Reparent the top layers for a display to the requested SurfaceControl. The display that is
|
||||
* going to be re-parented (the displayId passed in) needs to have been created by the same
|
||||
* process that is requesting the re-parent. This is to ensure clients can't just re-parent
|
||||
* display content info to any SurfaceControl, as this would be a security issue.
|
||||
*
|
||||
* @param window The window which owns the SurfaceControl. This indicates the z-order of the
|
||||
* windows of this display against the windows on the parent display.
|
||||
* @param sc The SurfaceControl that the top level layers for the display should be re-parented
|
||||
* to.
|
||||
* @param displayId The id of the display to be re-parented.
|
||||
*/
|
||||
void reparentDisplayContent(IWindow window, in SurfaceControl sc, int displayId);
|
||||
|
||||
/**
|
||||
* Update the location of a child display in its parent window. This enables windows in the
|
||||
* child display to compute the global transformation matrix.
|
||||
*
|
||||
* @param window The parent window of the display.
|
||||
* @param x The x coordinate in the parent window.
|
||||
* @param y The y coordinate in the parent window.
|
||||
* @param displayId The id of the display to be notified.
|
||||
*/
|
||||
void updateDisplayContentLocation(IWindow window, int x, int y, int displayId);
|
||||
|
||||
/**
|
||||
* Update a tap exclude region identified by provided id in the window. Touches on this region
|
||||
* will neither be dispatched to this window nor change the focus to this window. Passing an
|
||||
|
||||
@@ -1108,6 +1108,7 @@ final class AccessibilityController {
|
||||
// the window manager is still looking for where to put it.
|
||||
// We will do the work when we get a focus change callback.
|
||||
// TODO(b/112273690): Support multiple displays
|
||||
// TODO(b/129098348): Support embedded displays
|
||||
if (mService.getDefaultDisplayContentLocked().mCurrentFocus == null) {
|
||||
return;
|
||||
}
|
||||
@@ -1400,7 +1401,28 @@ final class AccessibilityController {
|
||||
if (w.isVisibleLw()) {
|
||||
outWindows.put(mTempLayer++, w);
|
||||
}
|
||||
}, false /* traverseTopToBottom */ );
|
||||
}, false /* traverseTopToBottom */);
|
||||
mService.mRoot.forAllWindows(w -> {
|
||||
final WindowState win = findRootDisplayParentWindow(w);
|
||||
if (win != null && win.getDisplayContent().isDefaultDisplay && w.isVisibleLw()) {
|
||||
// TODO(b/129098348): insert windows on child displays into outWindows based on
|
||||
// root-display-parent window.
|
||||
outWindows.put(mTempLayer++, w);
|
||||
}
|
||||
}, false /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
private WindowState findRootDisplayParentWindow(WindowState win) {
|
||||
WindowState displayParentWindow = win.getDisplayContent().getParentWindow();
|
||||
if (displayParentWindow == null) {
|
||||
return null;
|
||||
}
|
||||
WindowState candidate = displayParentWindow;
|
||||
while (candidate != null) {
|
||||
displayParentWindow = candidate;
|
||||
candidate = displayParentWindow.getDisplayContent().getParentWindow();
|
||||
}
|
||||
return displayParentWindow;
|
||||
}
|
||||
|
||||
private class MyHandler extends Handler {
|
||||
|
||||
@@ -144,6 +144,7 @@ import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
@@ -541,6 +542,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
private final InsetsStateController mInsetsStateController;
|
||||
|
||||
/** @see #getParentWindow() */
|
||||
private WindowState mParentWindow;
|
||||
|
||||
private Point mLocationInParentWindow = new Point();
|
||||
private SurfaceControl mParentSurfaceControl;
|
||||
private InputWindowHandle mPortalWindowHandle;
|
||||
|
||||
@@ -4923,11 +4928,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
/**
|
||||
* Re-parent the DisplayContent's top surfaces, {@link #mWindowingLayer} and
|
||||
* {@link #mOverlayLayer} to the specified surfaceControl.
|
||||
* {@link #mOverlayLayer} to the specified SurfaceControl.
|
||||
*
|
||||
* @param win The window which owns the SurfaceControl. This indicates the z-order of the
|
||||
* windows of this display against the windows on the parent display.
|
||||
* @param sc The new SurfaceControl, where the DisplayContent's surfaces will be re-parented to.
|
||||
*/
|
||||
void reparentDisplayContent(SurfaceControl sc) {
|
||||
void reparentDisplayContent(WindowState win, SurfaceControl sc) {
|
||||
mParentWindow = win;
|
||||
mParentSurfaceControl = sc;
|
||||
if (mPortalWindowHandle == null) {
|
||||
mPortalWindowHandle = createPortalWindowHandle(sc.toString());
|
||||
@@ -4936,6 +4944,41 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
.reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the window which owns the surface that this DisplayContent is re-parented to.
|
||||
*
|
||||
* @return the parent window.
|
||||
*/
|
||||
WindowState getParentWindow() {
|
||||
return mParentWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the location of this display in the parent window. This enables windows in this
|
||||
* display to compute the global transformation matrix.
|
||||
*
|
||||
* @param win The parent window of this display.
|
||||
* @param x The x coordinate in the parent window.
|
||||
* @param y The y coordinate in the parent window.
|
||||
*/
|
||||
void updateLocation(WindowState win, int x, int y) {
|
||||
if (mParentWindow != win) {
|
||||
throw new IllegalArgumentException(
|
||||
"The given window is not the parent window of this display.");
|
||||
}
|
||||
if (mLocationInParentWindow.x != x || mLocationInParentWindow.y != y) {
|
||||
mLocationInParentWindow.x = x;
|
||||
mLocationInParentWindow.y = y;
|
||||
if (mWmService.mAccessibilityController != null) {
|
||||
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Point getLocationInParentWindow() {
|
||||
return mLocationInParentWindow;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SurfaceControl getWindowingLayer() {
|
||||
return mWindowingLayer;
|
||||
|
||||
@@ -425,6 +425,16 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reparentDisplayContent(IWindow window, SurfaceControl sc, int displayId) {
|
||||
mService.reparentDisplayContent(window, sc, displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplayContentLocation(IWindow window, int x, int y, int displayId) {
|
||||
mService.updateDisplayContentLocation(window, x, y, displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTapExcludeRegion(IWindow window, int regionId, Region region) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
|
||||
@@ -1880,7 +1880,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
// We need to report touchable region changes to accessibility.
|
||||
if (mAccessibilityController != null
|
||||
&& w.getDisplayContent().getDisplayId() == DEFAULT_DISPLAY) {
|
||||
&& (w.getDisplayContent().getDisplayId() == DEFAULT_DISPLAY
|
||||
|| w.getDisplayContent().getParentWindow() != null)) {
|
||||
mAccessibilityController.onSomeWindowResizedOrMovedLocked();
|
||||
}
|
||||
}
|
||||
@@ -2012,7 +2013,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
if (((attrChanges & LayoutParams.ACCESSIBILITY_TITLE_CHANGED) != 0)
|
||||
&& (mAccessibilityController != null)
|
||||
&& (win.getDisplayId() == DEFAULT_DISPLAY)) {
|
||||
&& (win.getDisplayId() == DEFAULT_DISPLAY
|
||||
|| win.getDisplayContent().getParentWindow() != null)) {
|
||||
// No move or resize, but the controller checks for title changes as well
|
||||
mAccessibilityController.onSomeWindowResizedOrMovedLocked();
|
||||
}
|
||||
@@ -6703,6 +6705,61 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCallerOwnsDisplay(int displayId) {
|
||||
final Display display = mDisplayManager.getDisplay(displayId);
|
||||
if (display == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot find display for non-existent displayId: " + displayId);
|
||||
}
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int displayOwnerUid = display.getOwnerUid();
|
||||
if (callingUid != displayOwnerUid) {
|
||||
throw new SecurityException("The caller doesn't own the display.");
|
||||
}
|
||||
}
|
||||
|
||||
/** @see Session#reparentDisplayContent(IWindow, SurfaceControl, int) */
|
||||
void reparentDisplayContent(IWindow client, SurfaceControl sc, int displayId) {
|
||||
checkCallerOwnsDisplay(displayId);
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final WindowState win = windowForClientLocked(null, client, false);
|
||||
if (win == null) {
|
||||
Slog.w(TAG_WM, "Bad requesting window " + client);
|
||||
return;
|
||||
}
|
||||
getDisplayContentOrCreate(displayId, null).reparentDisplayContent(win, sc);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @see Session#updateDisplayContentLocation(IWindow, int, int, int) */
|
||||
void updateDisplayContentLocation(IWindow client, int x, int y, int displayId) {
|
||||
checkCallerOwnsDisplay(displayId);
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final WindowState win = windowForClientLocked(null, client, false);
|
||||
if (win == null) {
|
||||
Slog.w(TAG_WM, "Bad requesting window " + client);
|
||||
return;
|
||||
}
|
||||
final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
|
||||
if (displayContent != null) {
|
||||
displayContent.updateLocation(win, x, y);
|
||||
}
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a tap exclude region in the window identified by the provided id. Touches down on this
|
||||
* region will not:
|
||||
@@ -7537,31 +7594,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reparentDisplayContent(int displayId, SurfaceControl sc) {
|
||||
final Display display = mDisplayManager.getDisplay(displayId);
|
||||
if (display == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't reparent display for non-existent displayId: " + displayId);
|
||||
}
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
final int displayOwnerUid = display.getOwnerUid();
|
||||
if (callingUid != displayOwnerUid) {
|
||||
throw new SecurityException("Only owner of the display can reparent surfaces to it.");
|
||||
}
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
|
||||
displayContent.reparentDisplayContent(sc);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
|
||||
boolean shouldWaitForAnimToComplete = false;
|
||||
|
||||
@@ -3142,7 +3142,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
//TODO (multidisplay): Accessibility supported only for the default display.
|
||||
if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
|
||||
if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
|
||||
|| getDisplayContent().getParentWindow() != null)) {
|
||||
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
|
||||
}
|
||||
|
||||
@@ -4207,7 +4208,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
//TODO (multidisplay): Accessibility is supported only for the default display.
|
||||
if (mWmService.mAccessibilityController != null && getDisplayId() == DEFAULT_DISPLAY) {
|
||||
if (mWmService.mAccessibilityController != null && (getDisplayId() == DEFAULT_DISPLAY
|
||||
|| getDisplayContent().getParentWindow() != null)) {
|
||||
mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
|
||||
}
|
||||
|
||||
@@ -4646,6 +4648,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
int x = mSurfacePosition.x;
|
||||
int y = mSurfacePosition.y;
|
||||
|
||||
// We might be on a display which has been re-parented to a view in another window, so here
|
||||
// computes the global location of our display.
|
||||
DisplayContent dc = getDisplayContent();
|
||||
while (dc != null && dc.getParentWindow() != null) {
|
||||
final WindowState displayParent = dc.getParentWindow();
|
||||
x += displayParent.mWindowFrames.mFrame.left - displayParent.mAttrs.surfaceInsets.left
|
||||
+ (dc.getLocationInParentWindow().x * displayParent.mGlobalScale + 0.5f);
|
||||
y += displayParent.mWindowFrames.mFrame.top - displayParent.mAttrs.surfaceInsets.top
|
||||
+ (dc.getLocationInParentWindow().y * displayParent.mGlobalScale + 0.5f);
|
||||
dc = displayParent.getDisplayContent();
|
||||
}
|
||||
|
||||
// If changed, also adjust transformFrameToSurfacePosition
|
||||
final WindowContainer parent = getParent();
|
||||
if (isChildWindow()) {
|
||||
|
||||
@@ -493,4 +493,30 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
assertTrue(window.isVisible());
|
||||
assertTrue(window.isVisibleByPolicy());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTransformationMatrix() {
|
||||
synchronized (mWm.mGlobalLock) {
|
||||
final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0");
|
||||
win0.getFrameLw().offsetTo(1, 0);
|
||||
|
||||
final DisplayContent dc = createNewDisplay();
|
||||
dc.reparentDisplayContent(win0, win0.getSurfaceControl());
|
||||
dc.updateLocation(win0, 2, 0);
|
||||
|
||||
final float[] values = new float[9];
|
||||
final Matrix matrix = new Matrix();
|
||||
final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
|
||||
final WindowState win1 = createWindow(null, TYPE_APPLICATION, dc, "win1");
|
||||
win1.mHasSurface = true;
|
||||
win1.mSurfaceControl = mock(SurfaceControl.class);
|
||||
win1.getFrameLw().offsetTo(3, 0);
|
||||
win1.updateSurfacePosition(t);
|
||||
win1.getTransformationMatrix(values, matrix);
|
||||
|
||||
matrix.getValues(values);
|
||||
assertEquals(6f, values[Matrix.MTRANS_X], 0f);
|
||||
assertEquals(0f, values[Matrix.MTRANS_Y], 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user