Merge "Reduce unnecessary invocation of setInputWindowInfo"
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.view;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
@@ -31,17 +32,20 @@ public final class InputApplicationHandle {
|
||||
private long ptr;
|
||||
|
||||
// Application name.
|
||||
public String name;
|
||||
public final @NonNull String name;
|
||||
|
||||
// Dispatching timeout.
|
||||
public long dispatchingTimeoutMillis;
|
||||
public final long dispatchingTimeoutMillis;
|
||||
|
||||
public final IBinder token;
|
||||
public final @NonNull IBinder token;
|
||||
|
||||
private native void nativeDispose();
|
||||
|
||||
public InputApplicationHandle(IBinder token) {
|
||||
public InputApplicationHandle(@NonNull IBinder token, @NonNull String name,
|
||||
long dispatchingTimeoutMillis) {
|
||||
this.token = token;
|
||||
this.name = name;
|
||||
this.dispatchingTimeoutMillis = dispatchingTimeoutMillis;
|
||||
}
|
||||
|
||||
public InputApplicationHandle(InputApplicationHandle handle) {
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class InputWindowHandle {
|
||||
private long ptr;
|
||||
|
||||
// The input application handle.
|
||||
public final InputApplicationHandle inputApplicationHandle;
|
||||
public InputApplicationHandle inputApplicationHandle;
|
||||
|
||||
// The token associates input data with a window and its input channel. The client input
|
||||
// channel and the server input channel will both contain this token.
|
||||
|
||||
@@ -54,26 +54,28 @@ jobject NativeInputApplicationHandle::getInputApplicationHandleObjLocalRef(JNIEn
|
||||
|
||||
bool NativeInputApplicationHandle::updateInfo() {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jobject obj = env->NewLocalRef(mObjWeak);
|
||||
if (!obj) {
|
||||
ScopedLocalRef<jobject> obj(env, env->NewLocalRef(mObjWeak));
|
||||
if (!obj.get()) {
|
||||
return false;
|
||||
}
|
||||
if (mInfo.token.get() != nullptr) {
|
||||
// The java fields are immutable, so it doesn't need to update again.
|
||||
return true;
|
||||
}
|
||||
|
||||
mInfo.name = getStringField(env, obj, gInputApplicationHandleClassInfo.name, "<null>");
|
||||
mInfo.name = getStringField(env, obj.get(), gInputApplicationHandleClassInfo.name, "<null>");
|
||||
|
||||
mInfo.dispatchingTimeoutMillis =
|
||||
env->GetLongField(obj, gInputApplicationHandleClassInfo.dispatchingTimeoutMillis);
|
||||
env->GetLongField(obj.get(), gInputApplicationHandleClassInfo.dispatchingTimeoutMillis);
|
||||
|
||||
jobject tokenObj = env->GetObjectField(obj,
|
||||
gInputApplicationHandleClassInfo.token);
|
||||
if (tokenObj) {
|
||||
mInfo.token = ibinderForJavaObject(env, tokenObj);
|
||||
env->DeleteLocalRef(tokenObj);
|
||||
ScopedLocalRef<jobject> tokenObj(env, env->GetObjectField(obj.get(),
|
||||
gInputApplicationHandleClassInfo.token));
|
||||
if (tokenObj.get()) {
|
||||
mInfo.token = ibinderForJavaObject(env, tokenObj.get());
|
||||
} else {
|
||||
mInfo.token.clear();
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(obj);
|
||||
return mInfo.token.get() != nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -417,7 +417,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// mOccludesParent field.
|
||||
final boolean hasWallpaper;
|
||||
// Input application handle used by the input dispatcher.
|
||||
final InputApplicationHandle mInputApplicationHandle;
|
||||
private InputApplicationHandle mInputApplicationHandle;
|
||||
|
||||
final int launchedFromPid; // always the pid who started the activity.
|
||||
final int launchedFromUid; // always the uid who started the activity.
|
||||
@@ -1506,7 +1506,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
info = aInfo;
|
||||
mUserId = UserHandle.getUserId(info.applicationInfo.uid);
|
||||
packageName = info.applicationInfo.packageName;
|
||||
mInputApplicationHandle = new InputApplicationHandle(appToken);
|
||||
intent = _intent;
|
||||
|
||||
// If the class name in the intent doesn't match that of the target, this is probably an
|
||||
@@ -1693,6 +1692,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
return lockTaskLaunchMode;
|
||||
}
|
||||
|
||||
@NonNull InputApplicationHandle getInputApplicationHandle(boolean update) {
|
||||
if (mInputApplicationHandle == null) {
|
||||
mInputApplicationHandle = new InputApplicationHandle(appToken, toString(),
|
||||
mInputDispatchingTimeoutMillis);
|
||||
} else if (update) {
|
||||
final String name = toString();
|
||||
if (mInputDispatchingTimeoutMillis != mInputApplicationHandle.dispatchingTimeoutMillis
|
||||
|| !name.equals(mInputApplicationHandle.name)) {
|
||||
mInputApplicationHandle = new InputApplicationHandle(appToken, name,
|
||||
mInputDispatchingTimeoutMillis);
|
||||
}
|
||||
}
|
||||
return mInputApplicationHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
ActivityRecord asActivityRecord() {
|
||||
// I am an activity record!
|
||||
|
||||
@@ -277,9 +277,8 @@ class DragState {
|
||||
mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
|
||||
mService.mH.getLooper(), mDragDropController);
|
||||
|
||||
mDragApplicationHandle = new InputApplicationHandle(new Binder());
|
||||
mDragApplicationHandle.name = "drag";
|
||||
mDragApplicationHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||
mDragApplicationHandle = new InputApplicationHandle(new Binder(), "drag",
|
||||
DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
|
||||
|
||||
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
||||
display.getDisplayId());
|
||||
|
||||
@@ -175,11 +175,11 @@ class EmbeddedWindowController {
|
||||
|
||||
InputApplicationHandle getApplicationHandle() {
|
||||
if (mHostWindowState == null
|
||||
|| mHostWindowState.mInputWindowHandle.inputApplicationHandle == null) {
|
||||
|| mHostWindowState.mInputWindowHandle.getInputApplicationHandle() == null) {
|
||||
return null;
|
||||
}
|
||||
return new InputApplicationHandle(
|
||||
mHostWindowState.mInputWindowHandle.inputApplicationHandle);
|
||||
mHostWindowState.mInputWindowHandle.getInputApplicationHandle());
|
||||
}
|
||||
|
||||
InputChannel openInputChannel() {
|
||||
|
||||
@@ -63,9 +63,8 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
|
||||
mClientChannel.copyTo(inputChannel);
|
||||
}
|
||||
|
||||
mApplicationHandle = new InputApplicationHandle(new Binder());
|
||||
mApplicationHandle.name = name;
|
||||
mApplicationHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||
mApplicationHandle = new InputApplicationHandle(new Binder(), name,
|
||||
DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
|
||||
|
||||
mWindowHandle = new InputWindowHandle(mApplicationHandle, displayId);
|
||||
mWindowHandle.name = name;
|
||||
@@ -160,9 +159,11 @@ class InputConsumerImpl implements IBinder.DeathRecipient {
|
||||
public void binderDied() {
|
||||
synchronized (mService.getWindowManagerLock()) {
|
||||
// Clean up the input consumer
|
||||
final InputMonitor inputMonitor =
|
||||
mService.mRoot.getDisplayContent(mWindowHandle.displayId).getInputMonitor();
|
||||
inputMonitor.destroyInputConsumer(mName);
|
||||
final DisplayContent dc = mService.mRoot.getDisplayContent(mWindowHandle.displayId);
|
||||
if (dc == null) {
|
||||
return;
|
||||
}
|
||||
dc.getInputMonitor().destroyInputConsumer(mName);
|
||||
unlinkFromDeathRecipient();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
|
||||
import static com.android.server.wm.WindowManagerService.LOGTAG_INPUT_FOCUS;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
@@ -57,12 +58,12 @@ import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.EventLog;
|
||||
import android.util.Slog;
|
||||
import android.view.InputApplicationHandle;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputEventReceiver;
|
||||
import android.view.InputWindowHandle;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -81,7 +82,7 @@ final class InputMonitor {
|
||||
private boolean mUpdateInputWindowsImmediately;
|
||||
|
||||
private boolean mDisableWallpaperTouchEvents;
|
||||
private final Rect mTmpRect = new Rect();
|
||||
private final Region mTmpRegion = new Region();
|
||||
private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer;
|
||||
|
||||
private final int mDisplayId;
|
||||
@@ -276,66 +277,66 @@ final class InputMonitor {
|
||||
addInputConsumer(name, consumer);
|
||||
}
|
||||
|
||||
|
||||
void populateInputWindowHandle(final InputWindowHandle inputWindowHandle,
|
||||
final WindowState child, int flags, final int type, final boolean isVisible,
|
||||
final boolean focusable, final boolean hasWallpaper) {
|
||||
@VisibleForTesting
|
||||
void populateInputWindowHandle(final InputWindowHandleWrapper inputWindowHandle,
|
||||
final WindowState w) {
|
||||
// Add a window to our list of input windows.
|
||||
inputWindowHandle.name = child.toString();
|
||||
flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags);
|
||||
inputWindowHandle.layoutParamsFlags = flags;
|
||||
inputWindowHandle.layoutParamsType = type;
|
||||
inputWindowHandle.dispatchingTimeoutMillis = child.getInputDispatchingTimeoutMillis();
|
||||
inputWindowHandle.visible = isVisible;
|
||||
inputWindowHandle.focusable = focusable;
|
||||
inputWindowHandle.touchOcclusionMode = child.getTouchOcclusionMode();
|
||||
inputWindowHandle.hasWallpaper = hasWallpaper;
|
||||
inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false;
|
||||
inputWindowHandle.ownerPid = child.mSession.mPid;
|
||||
inputWindowHandle.ownerUid = child.mSession.mUid;
|
||||
inputWindowHandle.packageName = child.getOwningPackage();
|
||||
inputWindowHandle.inputFeatures = child.mAttrs.inputFeatures;
|
||||
inputWindowHandle.displayId = child.getDisplayId();
|
||||
inputWindowHandle.setInputApplicationHandle(w.mActivityRecord != null
|
||||
? w.mActivityRecord.getInputApplicationHandle(false /* update */) : null);
|
||||
inputWindowHandle.setToken(w.mInputChannelToken);
|
||||
inputWindowHandle.setDispatchingTimeoutMillis(w.getInputDispatchingTimeoutMillis());
|
||||
inputWindowHandle.setTouchOcclusionMode(w.getTouchOcclusionMode());
|
||||
inputWindowHandle.setInputFeatures(w.mAttrs.inputFeatures);
|
||||
inputWindowHandle.setPaused(w.mActivityRecord != null && w.mActivityRecord.paused);
|
||||
inputWindowHandle.setVisible(w.isVisible());
|
||||
|
||||
final Rect frame = child.getFrame();
|
||||
inputWindowHandle.frameLeft = frame.left;
|
||||
inputWindowHandle.frameTop = frame.top;
|
||||
inputWindowHandle.frameRight = frame.right;
|
||||
inputWindowHandle.frameBottom = frame.bottom;
|
||||
final boolean focusable = w.canReceiveKeys()
|
||||
&& (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
|
||||
inputWindowHandle.setFocusable(focusable);
|
||||
|
||||
final boolean hasWallpaper = mDisplayContent.mWallpaperController.isWallpaperTarget(w)
|
||||
&& !mService.mPolicy.isKeyguardShowing()
|
||||
&& !mDisableWallpaperTouchEvents;
|
||||
inputWindowHandle.setHasWallpaper(hasWallpaper);
|
||||
|
||||
final Rect frame = w.getFrame();
|
||||
inputWindowHandle.setFrame(frame.left, frame.top, frame.right, frame.bottom);
|
||||
|
||||
// Surface insets are hardcoded to be the same in all directions
|
||||
// and we could probably deprecate the "left/right/top/bottom" concept.
|
||||
// we avoid reintroducing this concept by just choosing one of them here.
|
||||
inputWindowHandle.surfaceInset = child.getAttrs().surfaceInsets.left;
|
||||
inputWindowHandle.setSurfaceInset(w.mAttrs.surfaceInsets.left);
|
||||
|
||||
/**
|
||||
* If the window is in a TaskManaged by a TaskOrganizer then most cropping
|
||||
* will be applied using the SurfaceControl hierarchy from the Organizer.
|
||||
* This means we need to make sure that these changes in crop are reflected
|
||||
* in the input windows, and so ensure this flag is set so that
|
||||
* the input crop always reflects the surface hierarchy.
|
||||
*
|
||||
* TODO(b/168252846): we have some issues with modal-windows, so we need to
|
||||
* cross that bridge now that we organize full-screen Tasks.
|
||||
*/
|
||||
if (child.getTask() != null
|
||||
&& child.getTask().isOrganized()
|
||||
&& child.getTask().getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
|
||||
inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */);
|
||||
// If we are scaling the window, input coordinates need to be inversely scaled to map from
|
||||
// what is on screen to what is actually being touched in the UI.
|
||||
inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f);
|
||||
|
||||
final int flags = w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs.flags);
|
||||
inputWindowHandle.setTouchableRegion(mTmpRegion);
|
||||
inputWindowHandle.setLayoutParamsFlags(flags);
|
||||
|
||||
boolean useSurfaceCrop = false;
|
||||
final Task task = w.getTask();
|
||||
if (task != null) {
|
||||
if (task.isOrganized() && task.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
|
||||
// If the window is in a TaskManaged by a TaskOrganizer then most cropping will
|
||||
// be applied using the SurfaceControl hierarchy from the Organizer. This means
|
||||
// we need to make sure that these changes in crop are reflected in the input
|
||||
// windows, and so ensure this flag is set so that the input crop always reflects
|
||||
// the surface hierarchy.
|
||||
// TODO(b/168252846): we have some issues with modal-windows, so we need to cross
|
||||
// that bridge now that we organize full-screen Tasks.
|
||||
inputWindowHandle.replaceTouchableRegionWithCrop(null /* Use this surfaces crop */);
|
||||
useSurfaceCrop = true;
|
||||
} else if (task.cropWindowsToStackBounds() && !w.inFreeformWindowingMode()) {
|
||||
inputWindowHandle.replaceTouchableRegionWithCrop(
|
||||
task.getRootTask().getSurfaceControl());
|
||||
useSurfaceCrop = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (child.mGlobalScale != 1) {
|
||||
// If we are scaling the window, input coordinates need
|
||||
// to be inversely scaled to map from what is on screen
|
||||
// to what is actually being touched in the UI.
|
||||
inputWindowHandle.scaleFactor = 1.0f/child.mGlobalScale;
|
||||
} else {
|
||||
inputWindowHandle.scaleFactor = 1;
|
||||
}
|
||||
|
||||
if (DEBUG_INPUT) {
|
||||
Slog.d(TAG_WM, "addInputWindowHandle: "
|
||||
+ child + ", " + inputWindowHandle);
|
||||
if (!useSurfaceCrop) {
|
||||
inputWindowHandle.setReplaceTouchableRegionWithCrop(false);
|
||||
inputWindowHandle.setTouchableRegionCrop(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,15 +402,8 @@ final class InputMonitor {
|
||||
|
||||
public void setFocusedAppLw(ActivityRecord newApp) {
|
||||
// Focused app has changed.
|
||||
if (newApp == null) {
|
||||
mService.mInputManager.setFocusedApplication(mDisplayId, null);
|
||||
} else {
|
||||
final InputApplicationHandle handle = newApp.mInputApplicationHandle;
|
||||
handle.name = newApp.toString();
|
||||
handle.dispatchingTimeoutMillis = newApp.mInputDispatchingTimeoutMillis;
|
||||
|
||||
mService.mInputManager.setFocusedApplication(mDisplayId, handle);
|
||||
}
|
||||
mService.mInputManager.setFocusedApplication(mDisplayId,
|
||||
newApp != null ? newApp.getInputApplicationHandle(true /* update */) : null);
|
||||
}
|
||||
|
||||
public void pauseDispatchingLw(WindowToken window) {
|
||||
@@ -456,10 +450,6 @@ final class InputMonitor {
|
||||
private boolean mAddRecentsAnimationInputConsumerHandle;
|
||||
|
||||
boolean mInDrag;
|
||||
WallpaperController mWallpaperController;
|
||||
|
||||
// An invalid window handle that tells SurfaceFlinger not update the input info.
|
||||
final InputWindowHandle mInvalidInputWindow = new InputWindowHandle(null, mDisplayId);
|
||||
|
||||
private void updateInputWindows(boolean inDrag) {
|
||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateInputWindows");
|
||||
@@ -474,10 +464,8 @@ final class InputMonitor {
|
||||
mAddWallpaperInputConsumerHandle = mWallpaperInputConsumer != null;
|
||||
mAddRecentsAnimationInputConsumerHandle = mRecentsAnimationInputConsumer != null;
|
||||
|
||||
mTmpRect.setEmpty();
|
||||
mDisableWallpaperTouchEvents = false;
|
||||
mInDrag = inDrag;
|
||||
mWallpaperController = mDisplayContent.mWallpaperController;
|
||||
|
||||
resetInputConsumers(mInputTransaction);
|
||||
|
||||
@@ -499,7 +487,7 @@ final class InputMonitor {
|
||||
}
|
||||
|
||||
final WindowState focus = mDisplayContent.mCurrentFocus;
|
||||
if (focus == null || focus.mInputWindowHandle.token == null) {
|
||||
if (focus == null || focus.mInputChannelToken == null) {
|
||||
mDisplayContent.mLastRequestedFocus = focus;
|
||||
return;
|
||||
}
|
||||
@@ -510,7 +498,7 @@ final class InputMonitor {
|
||||
return;
|
||||
}
|
||||
|
||||
mInputTransaction.setFocusedWindow(focus.mInputWindowHandle.token, mDisplayId);
|
||||
mInputTransaction.setFocusedWindow(focus.mInputChannelToken, mDisplayId);
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Focus request " + focus, "reason=UpdateInputWindows");
|
||||
mDisplayContent.mLastRequestedFocus = focus;
|
||||
@@ -519,33 +507,26 @@ final class InputMonitor {
|
||||
|
||||
@Override
|
||||
public void accept(WindowState w) {
|
||||
final InputChannel inputChannel = w.mInputChannel;
|
||||
final InputWindowHandle inputWindowHandle = w.mInputWindowHandle;
|
||||
final InputWindowHandleWrapper inputWindowHandle = w.mInputWindowHandle;
|
||||
final RecentsAnimationController recentsAnimationController =
|
||||
mService.getRecentsAnimationController();
|
||||
final boolean shouldApplyRecentsInputConsumer = recentsAnimationController != null
|
||||
&& recentsAnimationController.shouldApplyInputConsumer(w.mActivityRecord);
|
||||
final int type = w.mAttrs.type;
|
||||
final boolean isVisible = w.isVisibleLw();
|
||||
if (inputChannel == null || inputWindowHandle == null || w.mRemoved
|
||||
if (w.mInputChannelToken == null || w.mRemoved
|
||||
|| (!w.canReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) {
|
||||
if (w.mWinAnimator.hasSurface()) {
|
||||
// Assign an InputInfo with type to the overlay window which can't receive input
|
||||
// event. This is used to omit Surfaces from occlusion detection.
|
||||
populateOverlayInputInfo(mInvalidInputWindow, w.getName(), type, isVisible);
|
||||
mInputTransaction.setInputWindowInfo(
|
||||
w.mWinAnimator.mSurfaceController.mSurfaceControl,
|
||||
mInvalidInputWindow);
|
||||
populateOverlayInputInfo(inputWindowHandle, w.isVisible());
|
||||
setInputWindowInfoIfNeeded(mInputTransaction,
|
||||
w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
|
||||
return;
|
||||
}
|
||||
// Skip this window because it cannot possibly receive input.
|
||||
return;
|
||||
}
|
||||
|
||||
final int flags = w.mAttrs.flags;
|
||||
final int privateFlags = w.mAttrs.privateFlags;
|
||||
final boolean focusable = w.canReceiveKeys()
|
||||
&& (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
|
||||
|
||||
if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) {
|
||||
if (recentsAnimationController.updateInputConsumerForApp(
|
||||
@@ -584,47 +565,53 @@ final class InputMonitor {
|
||||
if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
|
||||
mDisableWallpaperTouchEvents = true;
|
||||
}
|
||||
final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(w)
|
||||
&& !mService.mPolicy.isKeyguardShowing()
|
||||
&& !mDisableWallpaperTouchEvents;
|
||||
|
||||
// If there's a drag in progress and 'child' is a potential drop target,
|
||||
// make sure it's been told about the drag
|
||||
if (mInDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
|
||||
if (mInDrag && w.isVisible() && w.getDisplayContent().isDefaultDisplay) {
|
||||
mService.mDragDropController.sendDragStartedIfNeededLocked(w);
|
||||
}
|
||||
|
||||
populateInputWindowHandle(
|
||||
inputWindowHandle, w, flags, type, isVisible, focusable, hasWallpaper);
|
||||
|
||||
// register key interception info
|
||||
mService.mKeyInterceptionInfoForToken.put(inputWindowHandle.token,
|
||||
mService.mKeyInterceptionInfoForToken.put(w.mInputChannelToken,
|
||||
w.getKeyInterceptionInfo());
|
||||
|
||||
if (w.mWinAnimator.hasSurface()) {
|
||||
mInputTransaction.setInputWindowInfo(
|
||||
populateInputWindowHandle(inputWindowHandle, w);
|
||||
setInputWindowInfoIfNeeded(mInputTransaction,
|
||||
w.mWinAnimator.mSurfaceController.mSurfaceControl, inputWindowHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void setInputWindowInfoIfNeeded(SurfaceControl.Transaction t, SurfaceControl sc,
|
||||
InputWindowHandleWrapper inputWindowHandle) {
|
||||
if (DEBUG_INPUT) {
|
||||
Slog.d(TAG_WM, "Update InputWindowHandle: " + inputWindowHandle);
|
||||
}
|
||||
if (inputWindowHandle.isChanged()) {
|
||||
inputWindowHandle.applyChangesToSurface(t, sc);
|
||||
}
|
||||
}
|
||||
|
||||
// This would reset InputWindowHandle fields to prevent it could be found by input event.
|
||||
// We need to check if any new field of InputWindowHandle could impact the result.
|
||||
private static void populateOverlayInputInfo(final InputWindowHandle inputWindowHandle,
|
||||
final String name, final int type, final boolean isVisible) {
|
||||
inputWindowHandle.name = name;
|
||||
inputWindowHandle.layoutParamsType = type;
|
||||
inputWindowHandle.dispatchingTimeoutMillis = 0; // it should never receive input
|
||||
inputWindowHandle.visible = isVisible;
|
||||
inputWindowHandle.focusable = false;
|
||||
inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL;
|
||||
inputWindowHandle.scaleFactor = 1;
|
||||
inputWindowHandle.layoutParamsFlags =
|
||||
FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE;
|
||||
inputWindowHandle.portalToDisplayId = INVALID_DISPLAY;
|
||||
inputWindowHandle.touchableRegion.setEmpty();
|
||||
@VisibleForTesting
|
||||
static void populateOverlayInputInfo(InputWindowHandleWrapper inputWindowHandle,
|
||||
boolean isVisible) {
|
||||
inputWindowHandle.setDispatchingTimeoutMillis(0); // It should never receive input.
|
||||
inputWindowHandle.setVisible(isVisible);
|
||||
inputWindowHandle.setFocusable(false);
|
||||
inputWindowHandle.setInputFeatures(INPUT_FEATURE_NO_INPUT_CHANNEL);
|
||||
// The input window handle without input channel must not have a token.
|
||||
inputWindowHandle.setToken(null);
|
||||
inputWindowHandle.setScaleFactor(1f);
|
||||
inputWindowHandle.setLayoutParamsFlags(
|
||||
FLAG_NOT_TOUCH_MODAL | FLAG_NOT_TOUCHABLE | FLAG_NOT_FOCUSABLE);
|
||||
inputWindowHandle.setPortalToDisplayId(INVALID_DISPLAY);
|
||||
inputWindowHandle.clearTouchableRegion();
|
||||
inputWindowHandle.setTouchableRegionCrop(null);
|
||||
inputWindowHandle.trustedOverlay = isTrustedOverlay(type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -635,9 +622,13 @@ final class InputMonitor {
|
||||
*/
|
||||
static void setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t,
|
||||
int displayId, String name) {
|
||||
InputWindowHandle inputWindowHandle = new InputWindowHandle(null, displayId);
|
||||
populateOverlayInputInfo(inputWindowHandle, name, TYPE_SECURE_SYSTEM_OVERLAY, true);
|
||||
t.setInputWindowInfo(sc, inputWindowHandle);
|
||||
final InputWindowHandleWrapper inputWindowHandle = new InputWindowHandleWrapper(
|
||||
new InputWindowHandle(null /* inputApplicationHandle */, displayId));
|
||||
inputWindowHandle.setName(name);
|
||||
inputWindowHandle.setLayoutParamsType(TYPE_SECURE_SYSTEM_OVERLAY);
|
||||
inputWindowHandle.setTrustedOverlay(true);
|
||||
populateOverlayInputInfo(inputWindowHandle, true /* isVisible */);
|
||||
setInputWindowInfoIfNeeded(t, sc, inputWindowHandle);
|
||||
}
|
||||
|
||||
static boolean isTrustedOverlay(int type) {
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Region;
|
||||
import android.os.IBinder;
|
||||
import android.view.InputApplicationHandle;
|
||||
import android.view.InputWindowHandle;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The wrapper of {@link InputWindowHandle} with field change detection to reduce unnecessary
|
||||
* updates to surface, e.g. if there are no changes, then skip invocation of
|
||||
* {@link SurfaceControl.Transaction#setInputWindowInfo(SurfaceControl, InputWindowHandle)}.
|
||||
*/
|
||||
class InputWindowHandleWrapper {
|
||||
/** The wrapped handle should not be directly exposed to avoid untracked changes. */
|
||||
private final @NonNull InputWindowHandle mHandle;
|
||||
|
||||
/** Whether the {@link #mHandle} is changed. */
|
||||
private boolean mChanged = true;
|
||||
|
||||
InputWindowHandleWrapper(@NonNull InputWindowHandle handle) {
|
||||
mHandle = handle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the input window handle has changed since the last invocation of
|
||||
* {@link #applyChangesToSurface(SurfaceControl.Transaction, SurfaceControl)}}
|
||||
*/
|
||||
boolean isChanged() {
|
||||
return mChanged;
|
||||
}
|
||||
|
||||
void forceChange() {
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void applyChangesToSurface(@NonNull SurfaceControl.Transaction t, @NonNull SurfaceControl sc) {
|
||||
t.setInputWindowInfo(sc, mHandle);
|
||||
mChanged = false;
|
||||
}
|
||||
|
||||
int getDisplayId() {
|
||||
return mHandle.displayId;
|
||||
}
|
||||
|
||||
InputApplicationHandle getInputApplicationHandle() {
|
||||
return mHandle.inputApplicationHandle;
|
||||
}
|
||||
|
||||
void setInputApplicationHandle(InputApplicationHandle handle) {
|
||||
if (mHandle.inputApplicationHandle == handle) {
|
||||
return;
|
||||
}
|
||||
mHandle.inputApplicationHandle = handle;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setToken(IBinder token) {
|
||||
if (mHandle.token == token) {
|
||||
return;
|
||||
}
|
||||
mHandle.token = token;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setName(String name) {
|
||||
if (Objects.equals(mHandle.name, name)) {
|
||||
return;
|
||||
}
|
||||
mHandle.name = name;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setLayoutParamsFlags(int flags) {
|
||||
if (mHandle.layoutParamsFlags == flags) {
|
||||
return;
|
||||
}
|
||||
mHandle.layoutParamsFlags = flags;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setLayoutParamsType(int type) {
|
||||
if (mHandle.layoutParamsType == type) {
|
||||
return;
|
||||
}
|
||||
mHandle.layoutParamsType = type;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setDispatchingTimeoutMillis(long timeout) {
|
||||
if (mHandle.dispatchingTimeoutMillis == timeout) {
|
||||
return;
|
||||
}
|
||||
mHandle.dispatchingTimeoutMillis = timeout;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setTouchableRegion(Region region) {
|
||||
if (mHandle.touchableRegion.equals(region)) {
|
||||
return;
|
||||
}
|
||||
mHandle.touchableRegion.set(region);
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void clearTouchableRegion() {
|
||||
if (mHandle.touchableRegion.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
mHandle.touchableRegion.setEmpty();
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setVisible(boolean visible) {
|
||||
if (mHandle.visible == visible) {
|
||||
return;
|
||||
}
|
||||
mHandle.visible = visible;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setFocusable(boolean focusable) {
|
||||
if (mHandle.focusable == focusable) {
|
||||
return;
|
||||
}
|
||||
mHandle.focusable = focusable;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setTouchOcclusionMode(int mode) {
|
||||
if (mHandle.touchOcclusionMode == mode) {
|
||||
return;
|
||||
}
|
||||
mHandle.touchOcclusionMode = mode;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setHasWallpaper(boolean hasWallpaper) {
|
||||
if (mHandle.hasWallpaper == hasWallpaper) {
|
||||
return;
|
||||
}
|
||||
mHandle.hasWallpaper = hasWallpaper;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setPaused(boolean paused) {
|
||||
if (mHandle.paused == paused) {
|
||||
return;
|
||||
}
|
||||
mHandle.paused = paused;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setTrustedOverlay(boolean trustedOverlay) {
|
||||
if (mHandle.trustedOverlay == trustedOverlay) {
|
||||
return;
|
||||
}
|
||||
mHandle.trustedOverlay = trustedOverlay;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setOwnerPid(int pid) {
|
||||
if (mHandle.ownerPid == pid) {
|
||||
return;
|
||||
}
|
||||
mHandle.ownerPid = pid;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setOwnerUid(int uid) {
|
||||
if (mHandle.ownerUid == uid) {
|
||||
return;
|
||||
}
|
||||
mHandle.ownerUid = uid;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setPackageName(String packageName) {
|
||||
if (Objects.equals(mHandle.packageName, packageName)) {
|
||||
return;
|
||||
}
|
||||
mHandle.packageName = packageName;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setInputFeatures(int features) {
|
||||
if (mHandle.inputFeatures == features) {
|
||||
return;
|
||||
}
|
||||
mHandle.inputFeatures = features;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setDisplayId(int displayId) {
|
||||
if (mHandle.displayId == displayId) {
|
||||
return;
|
||||
}
|
||||
mHandle.displayId = displayId;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setPortalToDisplayId(int displayId) {
|
||||
if (mHandle.portalToDisplayId == displayId) {
|
||||
return;
|
||||
}
|
||||
mHandle.portalToDisplayId = displayId;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setFrame(int left, int top, int right, int bottom) {
|
||||
if (mHandle.frameLeft == left && mHandle.frameTop == top && mHandle.frameRight == right
|
||||
&& mHandle.frameBottom == bottom) {
|
||||
return;
|
||||
}
|
||||
mHandle.frameLeft = left;
|
||||
mHandle.frameTop = top;
|
||||
mHandle.frameRight = right;
|
||||
mHandle.frameBottom = bottom;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setSurfaceInset(int inset) {
|
||||
if (mHandle.surfaceInset == inset) {
|
||||
return;
|
||||
}
|
||||
mHandle.surfaceInset = inset;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setScaleFactor(float scale) {
|
||||
if (mHandle.scaleFactor == scale) {
|
||||
return;
|
||||
}
|
||||
mHandle.scaleFactor = scale;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void replaceTouchableRegionWithCrop(@Nullable SurfaceControl bounds) {
|
||||
setTouchableRegionCrop(bounds);
|
||||
setReplaceTouchableRegionWithCrop(true);
|
||||
}
|
||||
|
||||
void setTouchableRegionCrop(@Nullable SurfaceControl bounds) {
|
||||
if (mHandle.touchableRegionSurfaceControl.get() == bounds) {
|
||||
return;
|
||||
}
|
||||
mHandle.setTouchableRegionCrop(bounds);
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
void setReplaceTouchableRegionWithCrop(boolean replace) {
|
||||
if (mHandle.replaceTouchableRegionWithCrop == replace) {
|
||||
return;
|
||||
}
|
||||
mHandle.replaceTouchableRegionWithCrop = replace;
|
||||
mChanged = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mHandle + ", changed=" + mChanged;
|
||||
}
|
||||
}
|
||||
@@ -225,10 +225,8 @@ class TaskPositioner implements IBinder.DeathRecipient {
|
||||
mClientChannel, mService.mAnimationHandler.getLooper(),
|
||||
mService.mAnimator.getChoreographer());
|
||||
|
||||
mDragApplicationHandle = new InputApplicationHandle(new Binder());
|
||||
mDragApplicationHandle.name = TAG;
|
||||
mDragApplicationHandle.dispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||
|
||||
mDragApplicationHandle = new InputApplicationHandle(new Binder(), TAG,
|
||||
DEFAULT_DISPATCHING_TIMEOUT_MILLIS);
|
||||
|
||||
mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle,
|
||||
displayContent.getDisplayId());
|
||||
|
||||
@@ -8395,7 +8395,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
embeddedWindow.getName());
|
||||
return;
|
||||
}
|
||||
t.requestFocusTransfer(newFocusTarget.mInputWindowHandle.token, targetInputToken,
|
||||
t.requestFocusTransfer(newFocusTarget.mInputChannelToken, targetInputToken,
|
||||
displayId).apply();
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Transfer focus request " + newFocusTarget,
|
||||
|
||||
@@ -556,9 +556,17 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
boolean mWindowRemovalAllowed;
|
||||
|
||||
// Input channel and input window handle used by the input dispatcher.
|
||||
final InputWindowHandle mInputWindowHandle;
|
||||
final InputWindowHandleWrapper mInputWindowHandle;
|
||||
InputChannel mInputChannel;
|
||||
|
||||
/**
|
||||
* The token will be assigned to {@link InputWindowHandle#token} if this window can receive
|
||||
* input event. Note that the token of associated input window handle can be cleared if this
|
||||
* window becomes unable to receive input, but this field will remain until the input channel
|
||||
* is actually disposed.
|
||||
*/
|
||||
IBinder mInputChannelToken;
|
||||
|
||||
// Used to improve performance of toString()
|
||||
private String mStringNameCache;
|
||||
private CharSequence mLastTitle;
|
||||
@@ -856,6 +864,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
DeathRecipient deathRecipient = new DeathRecipient();
|
||||
mPowerManagerWrapper = powerManagerWrapper;
|
||||
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
|
||||
mInputWindowHandle = new InputWindowHandleWrapper(new InputWindowHandle(
|
||||
mActivityRecord != null
|
||||
? mActivityRecord.getInputApplicationHandle(false /* update */) : null,
|
||||
getDisplayId()));
|
||||
mInputWindowHandle.setOwnerPid(s.mPid);
|
||||
mInputWindowHandle.setOwnerUid(s.mUid);
|
||||
mInputWindowHandle.setName(getName());
|
||||
mInputWindowHandle.setPackageName(mAttrs.packageName);
|
||||
mInputWindowHandle.setLayoutParamsType(mAttrs.type);
|
||||
// Check private trusted overlay flag and window type to set trustedOverlay variable of
|
||||
// input window handle.
|
||||
mInputWindowHandle.setTrustedOverlay(
|
||||
((mAttrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0
|
||||
&& mOwnerCanAddInternalSystemWindow)
|
||||
|| InputMonitor.isTrustedOverlay(mAttrs.type));
|
||||
if (DEBUG) {
|
||||
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
|
||||
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
|
||||
@@ -871,7 +894,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mIsFloatingLayer = false;
|
||||
mBaseLayer = 0;
|
||||
mSubLayer = 0;
|
||||
mInputWindowHandle = null;
|
||||
mWinAnimator = null;
|
||||
mWpcForDisplayConfigChanges = null;
|
||||
return;
|
||||
@@ -919,16 +941,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mLastRequestedWidth = 0;
|
||||
mLastRequestedHeight = 0;
|
||||
mLayer = 0;
|
||||
mInputWindowHandle = new InputWindowHandle(
|
||||
mActivityRecord != null ? mActivityRecord.mInputApplicationHandle : null,
|
||||
getDisplayId());
|
||||
|
||||
// Check private trusted overlay flag and window type to set trustedOverlay variable of
|
||||
// input window handle.
|
||||
mInputWindowHandle.trustedOverlay =
|
||||
(mAttrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0
|
||||
&& mOwnerCanAddInternalSystemWindow;
|
||||
mInputWindowHandle.trustedOverlay |= InputMonitor.isTrustedOverlay(mAttrs.type);
|
||||
|
||||
// Make sure we initial all fields before adding to parentWindow, to prevent exception
|
||||
// during onDisplayChanged.
|
||||
@@ -1496,9 +1508,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
super.onDisplayChanged(dc);
|
||||
// Window was not laid out for this display yet, so make sure mLayoutSeq does not match.
|
||||
if (dc != null && mInputWindowHandle.displayId != dc.getDisplayId()) {
|
||||
if (dc != null && mInputWindowHandle.getDisplayId() != dc.getDisplayId()) {
|
||||
mLayoutSeq = dc.mLayoutSeq - 1;
|
||||
mInputWindowHandle.displayId = dc.getDisplayId();
|
||||
mInputWindowHandle.setDisplayId(dc.getDisplayId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2470,7 +2482,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
String name = getName();
|
||||
mInputChannel = mWmService.mInputManager.createInputChannel(name);
|
||||
mInputWindowHandle.token = mInputChannel.getToken();
|
||||
mInputChannelToken = mInputChannel.getToken();
|
||||
mInputWindowHandle.setToken(mInputChannelToken);
|
||||
mWmService.mInputToWindowMap.put(mInputChannelToken, this);
|
||||
if (outInputChannel != null) {
|
||||
mInputChannel.copyTo(outInputChannel);
|
||||
} else {
|
||||
@@ -2479,7 +2493,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
// Create fake event receiver that simply reports all events as handled.
|
||||
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
|
||||
}
|
||||
mWmService.mInputToWindowMap.put(mInputWindowHandle.token, this);
|
||||
}
|
||||
|
||||
void disposeInputChannel() {
|
||||
@@ -2487,17 +2500,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
mDeadWindowEventReceiver.dispose();
|
||||
mDeadWindowEventReceiver = null;
|
||||
}
|
||||
if (mInputChannelToken != null) {
|
||||
// Unregister server channel first otherwise it complains about broken channel.
|
||||
mWmService.mInputManager.removeInputChannel(mInputChannelToken);
|
||||
mWmService.mKeyInterceptionInfoForToken.remove(mInputChannelToken);
|
||||
mWmService.mInputToWindowMap.remove(mInputChannelToken);
|
||||
mInputChannelToken = null;
|
||||
}
|
||||
|
||||
// unregister server channel first otherwise it complains about broken channel
|
||||
if (mInputChannel != null) {
|
||||
mWmService.mInputManager.removeInputChannel(mInputChannel.getToken());
|
||||
|
||||
mInputChannel.dispose();
|
||||
mInputChannel = null;
|
||||
}
|
||||
mWmService.mKeyInterceptionInfoForToken.remove(mInputWindowHandle.token);
|
||||
mWmService.mInputToWindowMap.remove(mInputWindowHandle.token);
|
||||
mInputWindowHandle.token = null;
|
||||
mInputWindowHandle.setToken(null);
|
||||
}
|
||||
|
||||
/** Returns true if the replacement window was removed. */
|
||||
@@ -2567,11 +2582,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
}
|
||||
|
||||
int getSurfaceTouchableRegion(InputWindowHandle inputWindowHandle, int flags) {
|
||||
int getSurfaceTouchableRegion(Region region, int flags) {
|
||||
final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
|
||||
final Region region = inputWindowHandle.touchableRegion;
|
||||
setTouchableRegionCropIfNeeded(inputWindowHandle);
|
||||
|
||||
if (modal) {
|
||||
flags |= FLAG_NOT_TOUCH_MODAL;
|
||||
if (mActivityRecord != null) {
|
||||
@@ -2593,7 +2605,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
// Translate to surface based coordinates.
|
||||
region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
|
||||
final Rect frame = mWindowFrames.mFrame;
|
||||
if (frame.left != 0 || frame.top != 0) {
|
||||
region.translate(-frame.left, -frame.top);
|
||||
}
|
||||
|
||||
// TODO(b/139804591): sizecompat layout needs to be reworked. Currently mFrame is post-
|
||||
// scaling but the existing logic doesn't expect that. The result is that the already-
|
||||
@@ -3442,7 +3457,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
break;
|
||||
case TOUCHABLE_INSETS_REGION: {
|
||||
outRegion.set(mGivenTouchableRegion);
|
||||
outRegion.translate(frame.left, frame.top);
|
||||
if (frame.left != 0 || frame.top != 0) {
|
||||
outRegion.translate(frame.left, frame.top);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3469,22 +3486,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
}
|
||||
|
||||
private void setTouchableRegionCropIfNeeded(InputWindowHandle handle) {
|
||||
final Task task = getTask();
|
||||
if (task == null || !task.cropWindowsToStackBounds()) {
|
||||
handle.setTouchableRegionCrop(null);
|
||||
return;
|
||||
}
|
||||
|
||||
final Task stack = task.getRootTask();
|
||||
if (stack == null || inFreeformWindowingMode()) {
|
||||
handle.setTouchableRegionCrop(null);
|
||||
return;
|
||||
}
|
||||
|
||||
handle.setTouchableRegionCrop(stack.getSurfaceControl());
|
||||
}
|
||||
|
||||
private void cropRegionToStackBoundsIfNeeded(Region region) {
|
||||
final Task task = getTask();
|
||||
if (task == null || !task.cropWindowsToStackBounds()) {
|
||||
|
||||
@@ -488,6 +488,9 @@ class WindowStateAnimator {
|
||||
mSurfaceFormat = format;
|
||||
|
||||
w.setHasSurface(true);
|
||||
// The surface instance is changed. Make sure the input info can be applied to the
|
||||
// new surface, e.g. relaunch activity.
|
||||
w.mInputWindowHandle.forceChange();
|
||||
|
||||
ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
|
||||
" CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s",
|
||||
|
||||
@@ -62,15 +62,18 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.util.Size;
|
||||
import android.view.DisplayCutout;
|
||||
import android.view.InputWindowHandle;
|
||||
import android.view.InsetsState;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
@@ -464,10 +467,10 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
public void testDisplayIdUpdatedOnReparent() {
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
// fake a different display
|
||||
app.mInputWindowHandle.displayId = mDisplayContent.getDisplayId() + 1;
|
||||
app.mInputWindowHandle.setDisplayId(mDisplayContent.getDisplayId() + 1);
|
||||
app.onDisplayChanged(mDisplayContent);
|
||||
|
||||
assertThat(app.mInputWindowHandle.displayId, is(mDisplayContent.getDisplayId()));
|
||||
assertThat(app.mInputWindowHandle.getDisplayId(), is(mDisplayContent.getDisplayId()));
|
||||
assertThat(app.getDisplayId(), is(mDisplayContent.getDisplayId()));
|
||||
}
|
||||
|
||||
@@ -678,6 +681,54 @@ public class WindowStateTests extends WindowTestsBase {
|
||||
assertFalse(win0.canReceiveTouchInput());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateInputWindowHandle() {
|
||||
final WindowState win = createWindow(null, TYPE_APPLICATION, "win");
|
||||
win.mAttrs.inputFeatures = WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
|
||||
final InputWindowHandle handle = new InputWindowHandle(
|
||||
win.mInputWindowHandle.getInputApplicationHandle(), win.getDisplayId());
|
||||
final InputWindowHandleWrapper handleWrapper = new InputWindowHandleWrapper(handle);
|
||||
final IBinder inputChannelToken = mock(IBinder.class);
|
||||
win.mInputChannelToken = inputChannelToken;
|
||||
|
||||
mDisplayContent.getInputMonitor().populateInputWindowHandle(handleWrapper, win);
|
||||
|
||||
assertTrue(handleWrapper.isChanged());
|
||||
assertEquals(inputChannelToken, handle.token);
|
||||
assertEquals(win.mActivityRecord.getInputApplicationHandle(false /* update */),
|
||||
handle.inputApplicationHandle);
|
||||
assertEquals(win.mAttrs.inputFeatures, handle.inputFeatures);
|
||||
assertEquals(win.isVisible(), handle.visible);
|
||||
|
||||
final SurfaceControl sc = mock(SurfaceControl.class);
|
||||
final SurfaceControl.Transaction transaction = mSystemServicesTestRule.mTransaction;
|
||||
InputMonitor.setInputWindowInfoIfNeeded(transaction, sc, handleWrapper);
|
||||
|
||||
// The fields of input window handle are changed, so it must set input window info
|
||||
// successfully. And then the changed flag should be reset.
|
||||
verify(transaction).setInputWindowInfo(eq(sc), eq(handle));
|
||||
assertFalse(handleWrapper.isChanged());
|
||||
// Populate the same states again, the handle should not detect change.
|
||||
mDisplayContent.getInputMonitor().populateInputWindowHandle(handleWrapper, win);
|
||||
assertFalse(handleWrapper.isChanged());
|
||||
|
||||
// Apply the no change handle, the invocation of setInputWindowInfo should be skipped.
|
||||
clearInvocations(transaction);
|
||||
InputMonitor.setInputWindowInfoIfNeeded(transaction, sc, handleWrapper);
|
||||
verify(transaction, never()).setInputWindowInfo(any(), any());
|
||||
|
||||
// Populate as an overlay to disable the input of window.
|
||||
InputMonitor.populateOverlayInputInfo(handleWrapper, false /* isVisible */);
|
||||
// The overlay attributes should be set.
|
||||
assertTrue(handleWrapper.isChanged());
|
||||
assertFalse(handle.focusable);
|
||||
assertFalse(handle.visible);
|
||||
assertNull(handle.token);
|
||||
assertEquals(0L, handle.dispatchingTimeoutMillis);
|
||||
assertEquals(WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL,
|
||||
handle.inputFeatures);
|
||||
}
|
||||
|
||||
@UseTestDisplay(addWindows = W_ACTIVITY)
|
||||
@Test
|
||||
public void testNeedsRelativeLayeringToIme_notAttached() {
|
||||
|
||||
Reference in New Issue
Block a user