Merge "Pass through some input-related layout flags for windowless surfaces"
This commit is contained in:
@@ -4979,6 +4979,11 @@ package android.view {
|
||||
method public abstract String asyncImpl() default "";
|
||||
}
|
||||
|
||||
public class SurfaceControlViewHost {
|
||||
method public void addView(@NonNull android.view.View, android.view.WindowManager.LayoutParams);
|
||||
method public void relayout(android.view.WindowManager.LayoutParams);
|
||||
}
|
||||
|
||||
@UiThread public class View implements android.view.accessibility.AccessibilityEventSource android.graphics.drawable.Drawable.Callback android.view.KeyEvent.Callback {
|
||||
method public android.view.View getTooltipView();
|
||||
method public boolean isAutofilled();
|
||||
|
||||
@@ -318,5 +318,11 @@ interface IWindowSession {
|
||||
* an input channel where the client can receive input.
|
||||
*/
|
||||
void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window,
|
||||
in IBinder hostInputToken, out InputChannel outInputChannel);
|
||||
in IBinder hostInputToken, int flags, out InputChannel outInputChannel);
|
||||
|
||||
/**
|
||||
* Update the flags on an input channel associated with a particular surface.
|
||||
*/
|
||||
void updateInputChannel(in IBinder channelToken, int displayId, in SurfaceControl surface,
|
||||
int flags);
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ public class SurfaceControlViewHost {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void addView(@NonNull View view, WindowManager.LayoutParams attrs) {
|
||||
mViewRoot.setView(view, attrs, null);
|
||||
}
|
||||
@@ -161,6 +162,7 @@ public class SurfaceControlViewHost {
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public void relayout(WindowManager.LayoutParams attrs) {
|
||||
mViewRoot.setLayoutParams(attrs, false);
|
||||
mViewRoot.setReportNextDraw();
|
||||
|
||||
@@ -41,9 +41,14 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
private class State {
|
||||
SurfaceControl mSurfaceControl;
|
||||
WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();
|
||||
State(SurfaceControl sc, WindowManager.LayoutParams p) {
|
||||
int mDisplayId;
|
||||
IBinder mInputChannelToken;
|
||||
State(SurfaceControl sc, WindowManager.LayoutParams p, int displayId,
|
||||
IBinder inputChannelToken) {
|
||||
mSurfaceControl = sc;
|
||||
mParams.copyFrom(p);
|
||||
mDisplayId = displayId;
|
||||
mInputChannelToken = inputChannelToken;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -105,19 +110,23 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
.setFormat(attrs.format)
|
||||
.setName(attrs.getTitle().toString());
|
||||
final SurfaceControl sc = b.build();
|
||||
synchronized (this) {
|
||||
mStateForWindow.put(window.asBinder(), new State(sc, attrs));
|
||||
}
|
||||
|
||||
if (((attrs.inputFeatures &
|
||||
WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
|
||||
try {
|
||||
mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, outInputChannel);
|
||||
mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags,
|
||||
outInputChannel);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to bless surface: " + e);
|
||||
Log.e(TAG, "Failed to grant input to surface: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
final State state = new State(sc, attrs, displayId,
|
||||
outInputChannel != null ? outInputChannel.getToken() : null);
|
||||
synchronized (this) {
|
||||
mStateForWindow.put(window.asBinder(), state);
|
||||
}
|
||||
|
||||
return WindowManagerGlobal.ADD_OKAY | WindowManagerGlobal.ADD_FLAG_APP_VISIBLE;
|
||||
}
|
||||
|
||||
@@ -162,7 +171,7 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration,
|
||||
SurfaceControl outSurfaceControl, InsetsState outInsetsState,
|
||||
Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) {
|
||||
State state = null;
|
||||
final State state;
|
||||
synchronized (this) {
|
||||
state = mStateForWindow.get(window.asBinder());
|
||||
}
|
||||
@@ -173,8 +182,9 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
SurfaceControl sc = state.mSurfaceControl;
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
|
||||
int attrChanges = 0;
|
||||
if (inAttrs != null) {
|
||||
state.mParams.copyFrom(inAttrs);
|
||||
attrChanges = state.mParams.copyFrom(inAttrs);
|
||||
}
|
||||
WindowManager.LayoutParams attrs = state.mParams;
|
||||
|
||||
@@ -197,6 +207,16 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
|
||||
mergedConfiguration.setConfiguration(mConfiguration, mConfiguration);
|
||||
|
||||
if ((attrChanges & WindowManager.LayoutParams.FLAGS_CHANGED) != 0
|
||||
&& state.mInputChannelToken != null) {
|
||||
try {
|
||||
mRealWm.updateInputChannel(state.mInputChannelToken, state.mDisplayId, sc,
|
||||
attrs.flags);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to update surface input channel: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -353,7 +373,12 @@ public class WindowlessWindowManager implements IWindowSession {
|
||||
|
||||
@Override
|
||||
public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window,
|
||||
IBinder hostInputToken, InputChannel outInputChannel) {
|
||||
IBinder hostInputToken, int flags, InputChannel outInputChannel) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
|
||||
int flags) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,8 +20,10 @@ package com.android.server.wm;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.IWindow;
|
||||
import android.view.InputApplicationHandle;
|
||||
|
||||
/**
|
||||
* Keeps track of embedded windows.
|
||||
@@ -44,21 +46,12 @@ class EmbeddedWindowController {
|
||||
*
|
||||
* @param inputToken input channel token passed in by the embedding process when it requests
|
||||
* the server to add an input channel to the embedded surface.
|
||||
* @param window client token used to clean up the map if the embedding process dies
|
||||
* @param hostWindowState input channel token belonging to the host window. This is needed to
|
||||
* handle input callbacks to wm. It's used when raising ANR and when
|
||||
* the user taps out side of the focused region on screen. This can be
|
||||
* null if there is no host window.
|
||||
* @param ownerUid calling uid
|
||||
* @param ownerPid calling pid used for anr blaming
|
||||
* @param embeddedWindow An {@link EmbeddedWindow} object to add to this controller.
|
||||
*/
|
||||
void add(IBinder inputToken, IWindow window, @Nullable WindowState hostWindowState,
|
||||
int ownerUid, int ownerPid) {
|
||||
EmbeddedWindow embeddedWindow = new EmbeddedWindow(window, hostWindowState, ownerUid,
|
||||
ownerPid);
|
||||
void add(IBinder inputToken, EmbeddedWindow embeddedWindow) {
|
||||
try {
|
||||
mWindows.put(inputToken, embeddedWindow);
|
||||
window.asBinder().linkToDeath(()-> {
|
||||
embeddedWindow.mClient.asBinder().linkToDeath(()-> {
|
||||
synchronized (mWmLock) {
|
||||
mWindows.remove(inputToken);
|
||||
}
|
||||
@@ -101,6 +94,15 @@ class EmbeddedWindowController {
|
||||
final int mOwnerUid;
|
||||
final int mOwnerPid;
|
||||
|
||||
/**
|
||||
* @param clientToken client token used to clean up the map if the embedding process dies
|
||||
* @param hostWindowState input channel token belonging to the host window. This is needed
|
||||
* to handle input callbacks to wm. It's used when raising ANR and
|
||||
* when the user taps out side of the focused region on screen. This
|
||||
* can be null if there is no host window.
|
||||
* @param ownerUid calling uid
|
||||
* @param ownerPid calling pid used for anr blaming
|
||||
*/
|
||||
EmbeddedWindow(IWindow clientToken, WindowState hostWindowState, int ownerUid,
|
||||
int ownerPid) {
|
||||
mClient = clientToken;
|
||||
@@ -108,5 +110,21 @@ class EmbeddedWindowController {
|
||||
mOwnerUid = ownerUid;
|
||||
mOwnerPid = ownerPid;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
final String hostWindowName = (mHostWindowState != null)
|
||||
? mHostWindowState.getWindowTag().toString() : "Internal";
|
||||
return "EmbeddedWindow{ u" + UserHandle.getUserId(mOwnerUid) + " " + hostWindowName
|
||||
+ "}";
|
||||
}
|
||||
|
||||
InputApplicationHandle getApplicationHandle() {
|
||||
if (mHostWindowState == null
|
||||
|| mHostWindowState.mInputWindowHandle.inputApplicationHandle == null) {
|
||||
return null;
|
||||
}
|
||||
return new InputApplicationHandle(
|
||||
mHostWindowState.mInputWindowHandle.inputApplicationHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +622,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
|
||||
@Override
|
||||
public void grantInputChannel(int displayId, SurfaceControl surface,
|
||||
IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
|
||||
IWindow window, IBinder hostInputToken, int flags, InputChannel outInputChannel) {
|
||||
if (hostInputToken == null && !mCanAddInternalSystemWindow) {
|
||||
// Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
|
||||
// embedded windows without providing a host window input token
|
||||
@@ -631,8 +631,19 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
|
||||
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mService.grantInputChannel(mUid, mPid, displayId, surface, window,
|
||||
hostInputToken, outInputChannel);
|
||||
mService.grantInputChannel(mUid, mPid, displayId, surface, window, hostInputToken,
|
||||
flags, outInputChannel);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
|
||||
int flags) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mService.updateInputChannel(channelToken, displayId, surface, flags);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
|
||||
@@ -7814,40 +7814,52 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
* views.
|
||||
*/
|
||||
void grantInputChannel(int callingUid, int callingPid, int displayId, SurfaceControl surface,
|
||||
IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
|
||||
InputApplicationHandle applicationHandle = null;
|
||||
IWindow window, IBinder hostInputToken, int flags, InputChannel outInputChannel) {
|
||||
final InputApplicationHandle applicationHandle;
|
||||
final String name;
|
||||
final InputChannel[] inputChannels;
|
||||
final InputChannel clientChannel;
|
||||
final InputChannel serverChannel;
|
||||
synchronized (mGlobalLock) {
|
||||
final WindowState hostWindow = mInputToWindowMap.get(hostInputToken);
|
||||
final String hostWindowName = (hostWindow != null)
|
||||
? hostWindow.getWindowTag().toString() : "Internal";
|
||||
name = "EmbeddedWindow{ u" + UserHandle.getUserId(callingUid)
|
||||
+ " " + hostWindowName + "}";
|
||||
EmbeddedWindowController.EmbeddedWindow win =
|
||||
new EmbeddedWindowController.EmbeddedWindow(window,
|
||||
mInputToWindowMap.get(hostInputToken), callingUid, callingPid);
|
||||
name = win.getName();
|
||||
|
||||
inputChannels = InputChannel.openInputChannelPair(name);
|
||||
serverChannel = inputChannels[0];
|
||||
clientChannel = inputChannels[1];
|
||||
mInputManager.registerInputChannel(serverChannel);
|
||||
mEmbeddedWindowController.add(serverChannel.getToken(), window, hostWindow, callingUid,
|
||||
callingPid);
|
||||
|
||||
if (hostWindow != null
|
||||
&& hostWindow.mInputWindowHandle.inputApplicationHandle != null) {
|
||||
applicationHandle = new InputApplicationHandle(
|
||||
hostWindow.mInputWindowHandle.inputApplicationHandle);
|
||||
mEmbeddedWindowController.add(clientChannel.getToken(), win);
|
||||
if (serverChannel.getToken() != clientChannel.getToken()) {
|
||||
throw new IllegalStateException("Client and Server channel are expected to"
|
||||
+ "be the same");
|
||||
}
|
||||
|
||||
applicationHandle = win.getApplicationHandle();
|
||||
}
|
||||
|
||||
updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
|
||||
name, applicationHandle, flags);
|
||||
|
||||
clientChannel.transferTo(outInputChannel);
|
||||
clientChannel.dispose();
|
||||
// Prevent the java finalizer from breaking the input channel. But we won't
|
||||
// do any further management so we just release the java ref and let the
|
||||
// InputDispatcher hold the last ref.
|
||||
serverChannel.release();
|
||||
}
|
||||
|
||||
private void updateInputChannel(IBinder channelToken, int callingUid, int callingPid,
|
||||
int displayId, SurfaceControl surface, String name,
|
||||
InputApplicationHandle applicationHandle, int flags) {
|
||||
InputWindowHandle h = new InputWindowHandle(applicationHandle, displayId);
|
||||
h.token = serverChannel.getToken();
|
||||
h.token = channelToken;
|
||||
h.name = name;
|
||||
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
|
||||
|
||||
final int sanitizedFlags = flags & (LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
| LayoutParams.FLAG_SLIPPERY);
|
||||
h.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | sanitizedFlags;
|
||||
h.layoutParamsType = 0;
|
||||
h.dispatchingTimeoutNanos = -1;
|
||||
h.canReceiveKeys = false;
|
||||
@@ -7862,15 +7874,34 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
h.replaceTouchableRegionWithCrop(null);
|
||||
|
||||
SurfaceSession s = new SurfaceSession();
|
||||
SurfaceControl.Transaction t = mTransactionFactory.get();
|
||||
t.setInputWindowInfo(surface, h);
|
||||
t.apply();
|
||||
t.close();
|
||||
}
|
||||
|
||||
// Prevent the java finalizer from breaking the input channel. But we won't
|
||||
// do any further management so we just release the java ref and let the
|
||||
// InputDispatcher hold the last ref.
|
||||
serverChannel.release();
|
||||
/**
|
||||
* Updates the flags on an existing surface's input channel. This assumes the surface provided
|
||||
* is the one associated with the provided input-channel. If this isn't the case, behavior
|
||||
* is undefined.
|
||||
*/
|
||||
void updateInputChannel(IBinder channelToken, int displayId, SurfaceControl surface,
|
||||
int flags) {
|
||||
final InputApplicationHandle applicationHandle;
|
||||
final String name;
|
||||
final EmbeddedWindowController.EmbeddedWindow win;
|
||||
synchronized (mGlobalLock) {
|
||||
win = mEmbeddedWindowController.get(channelToken);
|
||||
if (win == null) {
|
||||
Slog.e(TAG, "Couldn't find window for provided channelToken.");
|
||||
return;
|
||||
}
|
||||
name = win.getName();
|
||||
applicationHandle = win.getApplicationHandle();
|
||||
}
|
||||
|
||||
updateInputChannel(channelToken, win.mOwnerUid, win.mOwnerPid, displayId, surface, name,
|
||||
applicationHandle, flags);
|
||||
}
|
||||
|
||||
/** Return whether layer tracing is enabled */
|
||||
|
||||
Reference in New Issue
Block a user