Merge "WM: Track focus changes in AccessibilityController" into sc-v2-dev am: d54349db7c
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15640923 Change-Id: I69993ec8d57fb34fff97bbd3a69b64bddec5144a
This commit is contained in:
@@ -50,6 +50,7 @@ import android.accessibilityservice.AccessibilityTrace;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
@@ -134,6 +135,8 @@ final class AccessibilityController {
|
||||
private SparseArray<DisplayMagnifier> mDisplayMagnifiers = new SparseArray<>();
|
||||
private SparseArray<WindowsForAccessibilityObserver> mWindowsForAccessibilityObserver =
|
||||
new SparseArray<>();
|
||||
private SparseArray<IBinder> mFocusedWindow = new SparseArray<>();
|
||||
private int mFocusedDisplay = -1;
|
||||
|
||||
// Set to true if initializing window population complete.
|
||||
private boolean mAllObserversInitialized = true;
|
||||
@@ -603,6 +606,29 @@ final class AccessibilityController {
|
||||
return display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null;
|
||||
}
|
||||
|
||||
void onFocusChanged(InputTarget lastTarget, InputTarget newTarget) {
|
||||
if (lastTarget != null) {
|
||||
mFocusedWindow.remove(lastTarget.getDisplayId());
|
||||
}
|
||||
if (newTarget != null) {
|
||||
int displayId = newTarget.getDisplayId();
|
||||
IBinder clientBinder = newTarget.getIWindow().asBinder();
|
||||
mFocusedWindow.put(displayId, clientBinder);
|
||||
}
|
||||
}
|
||||
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
mFocusedWindow.remove(displayId);
|
||||
}
|
||||
|
||||
public void setFocusedDisplay(int focusedDisplayId) {
|
||||
mFocusedDisplay = focusedDisplayId;
|
||||
}
|
||||
|
||||
@Nullable IBinder getFocusedWindowToken() {
|
||||
return mFocusedWindow.get(mFocusedDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class encapsulates the functionality related to display magnification.
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.util.SparseArray;
|
||||
import android.view.InputApplicationHandle;
|
||||
|
||||
import com.android.server.am.ActivityManagerService;
|
||||
import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -81,21 +80,19 @@ class AnrController {
|
||||
final boolean aboveSystem;
|
||||
final ActivityRecord activity;
|
||||
synchronized (mService.mGlobalLock) {
|
||||
WindowState windowState = mService.mInputToWindowMap.get(inputToken);
|
||||
if (windowState != null) {
|
||||
pid = windowState.mSession.mPid;
|
||||
activity = windowState.mActivityRecord;
|
||||
Slog.i(TAG_WM, "ANR in " + windowState.mAttrs.getTitle() + ". Reason:" + reason);
|
||||
} else {
|
||||
EmbeddedWindow embeddedWindow = mService.mEmbeddedWindowController.get(inputToken);
|
||||
if (embeddedWindow == null) {
|
||||
Slog.e(TAG_WM, "Unknown token, dropping notifyConnectionUnresponsive request");
|
||||
return;
|
||||
}
|
||||
pid = embeddedWindow.mOwnerPid;
|
||||
windowState = embeddedWindow.mHostWindowState;
|
||||
activity = null; // Don't blame the host process, instead blame the embedded pid.
|
||||
InputTarget target = mService.getInputTargetFromToken(inputToken);
|
||||
if (target == null) {
|
||||
Slog.e(TAG_WM, "Unknown token, dropping notifyConnectionUnresponsive request");
|
||||
return;
|
||||
}
|
||||
|
||||
WindowState windowState = target.getWindowState();
|
||||
pid = target.getPid();
|
||||
// Blame the activity if the input token belongs to the window. If the target is
|
||||
// embedded, then we will blame the pid instead.
|
||||
activity = (windowState.mInputChannelToken == inputToken)
|
||||
? windowState.mActivityRecord : null;
|
||||
Slog.i(TAG_WM, "ANR in " + target + ". Reason:" + reason);
|
||||
aboveSystem = isWindowAboveSystem(windowState);
|
||||
dumpAnrStateLocked(activity, windowState, reason);
|
||||
}
|
||||
@@ -109,19 +106,12 @@ class AnrController {
|
||||
void notifyWindowResponsive(IBinder inputToken) {
|
||||
final int pid;
|
||||
synchronized (mService.mGlobalLock) {
|
||||
WindowState windowState = mService.mInputToWindowMap.get(inputToken);
|
||||
if (windowState != null) {
|
||||
pid = windowState.mSession.mPid;
|
||||
} else {
|
||||
// Check if the token belongs to an embedded window.
|
||||
EmbeddedWindow embeddedWindow = mService.mEmbeddedWindowController.get(inputToken);
|
||||
if (embeddedWindow == null) {
|
||||
Slog.e(TAG_WM,
|
||||
"Unknown token, dropping notifyWindowConnectionResponsive request");
|
||||
return;
|
||||
}
|
||||
pid = embeddedWindow.mOwnerPid;
|
||||
InputTarget target = mService.getInputTargetFromToken(inputToken);
|
||||
if (target == null) {
|
||||
Slog.e(TAG_WM, "Unknown token, dropping notifyWindowConnectionResponsive request");
|
||||
return;
|
||||
}
|
||||
pid = target.getPid();
|
||||
}
|
||||
mService.mAmInternal.inputDispatchingResumed(pid);
|
||||
}
|
||||
|
||||
@@ -3099,6 +3099,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
mOverlayLayer.release();
|
||||
mInputMonitor.onDisplayRemoved();
|
||||
mWmService.mDisplayNotificationController.dispatchDisplayRemoved(this);
|
||||
mWmService.mAccessibilityController.onDisplayRemoved(mDisplayId);
|
||||
} finally {
|
||||
mDisplayReady = false;
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ class EmbeddedWindowController {
|
||||
}
|
||||
}
|
||||
|
||||
static class EmbeddedWindow {
|
||||
static class EmbeddedWindow implements InputTarget {
|
||||
final IWindow mClient;
|
||||
@Nullable final WindowState mHostWindowState;
|
||||
@Nullable final ActivityRecord mHostActivityRecord;
|
||||
@@ -166,7 +166,8 @@ class EmbeddedWindowController {
|
||||
mDisplayId = displayId;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
@Override
|
||||
public String toString() {
|
||||
final String hostWindowName = (mHostWindowState != null)
|
||||
? mHostWindowState.getWindowTag().toString() : "Internal";
|
||||
return "EmbeddedWindow{ u" + UserHandle.getUserId(mOwnerUid) + " " + hostWindowName
|
||||
@@ -183,7 +184,7 @@ class EmbeddedWindowController {
|
||||
}
|
||||
|
||||
InputChannel openInputChannel() {
|
||||
final String name = getName();
|
||||
final String name = toString();
|
||||
mInputChannel = mWmService.mInputManager.createInputChannel(name);
|
||||
return mInputChannel;
|
||||
}
|
||||
@@ -195,5 +196,25 @@ class EmbeddedWindowController {
|
||||
mInputChannel = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindowState() {
|
||||
return mHostWindowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDisplayId() {
|
||||
return mDisplayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWindow getIWindow() {
|
||||
return mClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPid() {
|
||||
return mOwnerPid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
services/core/java/com/android/server/wm/InputTarget.java
Normal file
40
services/core/java/com/android/server/wm/InputTarget.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.view.IWindow;
|
||||
|
||||
/**
|
||||
* Common interface between focusable objects.
|
||||
*
|
||||
* Both WindowState and EmbeddedWindows can receive input. This consolidates some common properties
|
||||
* of both targets.
|
||||
*/
|
||||
interface InputTarget {
|
||||
/* Get the WindowState associated with the target. */
|
||||
WindowState getWindowState();
|
||||
|
||||
/* Display id of the target. */
|
||||
int getDisplayId();
|
||||
|
||||
/* Client IWindow for the target. */
|
||||
IWindow getIWindow();
|
||||
|
||||
/* Owning pid of the target. */
|
||||
int getPid();
|
||||
}
|
||||
|
||||
@@ -504,6 +504,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
mTopFocusedDisplayId = topFocusedDisplayId;
|
||||
mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId);
|
||||
mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId);
|
||||
mWmService.mAccessibilityController.setFocusedDisplay(topFocusedDisplayId);
|
||||
ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId);
|
||||
}
|
||||
return changed;
|
||||
|
||||
@@ -4981,23 +4981,49 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
return Surface.ROTATION_0;
|
||||
}
|
||||
|
||||
void reportFocusChanged(IBinder oldToken, IBinder newToken) {
|
||||
WindowState lastFocus;
|
||||
WindowState newFocus;
|
||||
synchronized (mGlobalLock) {
|
||||
lastFocus = mInputToWindowMap.get(oldToken);
|
||||
newFocus = mInputToWindowMap.get(newToken);
|
||||
ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastFocus, newFocus);
|
||||
// Returns an input target which is mapped to the given input token. This can be a WindowState
|
||||
// or an embedded window.
|
||||
@Nullable InputTarget getInputTargetFromToken(IBinder inputToken) {
|
||||
WindowState windowState = mInputToWindowMap.get(inputToken);
|
||||
if (windowState != null) {
|
||||
return windowState;
|
||||
}
|
||||
|
||||
if (newFocus != null) {
|
||||
mAnrController.onFocusChanged(newFocus);
|
||||
newFocus.reportFocusChangedSerialized(true);
|
||||
EmbeddedWindowController.EmbeddedWindow embeddedWindow =
|
||||
mEmbeddedWindowController.get(inputToken);
|
||||
if (embeddedWindow != null) {
|
||||
return embeddedWindow;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void reportFocusChanged(IBinder oldToken, IBinder newToken) {
|
||||
InputTarget lastTarget;
|
||||
InputTarget newTarget;
|
||||
synchronized (mGlobalLock) {
|
||||
lastTarget = getInputTargetFromToken(oldToken);
|
||||
newTarget = getInputTargetFromToken(newToken);
|
||||
if (newTarget == null && lastTarget == null) {
|
||||
Slog.v(TAG_WM, "Unknown focus tokens, dropping reportFocusChanged");
|
||||
return;
|
||||
}
|
||||
|
||||
mAccessibilityController.onFocusChanged(lastTarget, newTarget);
|
||||
ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus changing: %s -> %s", lastTarget, newTarget);
|
||||
}
|
||||
|
||||
// Call WindowState focus change observers
|
||||
WindowState newFocusedWindow = newTarget != null ? newTarget.getWindowState() : null;
|
||||
if (newFocusedWindow != null && newFocusedWindow.mInputChannelToken == newToken) {
|
||||
mAnrController.onFocusChanged(newFocusedWindow);
|
||||
newFocusedWindow.reportFocusChangedSerialized(true);
|
||||
notifyFocusChanged();
|
||||
}
|
||||
|
||||
if (lastFocus != null) {
|
||||
lastFocus.reportFocusChangedSerialized(false);
|
||||
WindowState lastFocusedWindow = lastTarget != null ? lastTarget.getWindowState() : null;
|
||||
if (lastFocusedWindow != null && lastFocusedWindow.mInputChannelToken == oldToken) {
|
||||
lastFocusedWindow.reportFocusChangedSerialized(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7522,11 +7548,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
@Override
|
||||
public IBinder getFocusedWindowToken() {
|
||||
synchronized (mGlobalLock) {
|
||||
WindowState windowState = getFocusedWindowLocked();
|
||||
if (windowState != null) {
|
||||
return windowState.mClient.asBinder();
|
||||
}
|
||||
return null;
|
||||
return mAccessibilityController.getFocusedWindowToken();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8267,7 +8289,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
clientChannel = win.openInputChannel();
|
||||
mEmbeddedWindowController.add(clientChannel.getToken(), win);
|
||||
applicationHandle = win.getApplicationHandle();
|
||||
name = win.getName();
|
||||
name = win.toString();
|
||||
}
|
||||
|
||||
updateInputChannel(clientChannel.getToken(), callingUid, callingPid, displayId, surface,
|
||||
@@ -8333,7 +8355,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
Slog.e(TAG, "Couldn't find window for provided channelToken.");
|
||||
return;
|
||||
}
|
||||
name = win.getName();
|
||||
name = win.toString();
|
||||
applicationHandle = win.getApplicationHandle();
|
||||
}
|
||||
|
||||
@@ -8542,10 +8564,9 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
SurfaceControl.Transaction t = mTransactionFactory.get();
|
||||
final int displayId = embeddedWindow.mDisplayId;
|
||||
if (grantFocus) {
|
||||
t.setFocusedWindow(inputToken, embeddedWindow.getName(), displayId).apply();
|
||||
t.setFocusedWindow(inputToken, embeddedWindow.toString(), displayId).apply();
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Focus request " + embeddedWindow.getName(),
|
||||
"reason=grantEmbeddedWindowFocus(true)");
|
||||
"Focus request " + embeddedWindow, "reason=grantEmbeddedWindowFocus(true)");
|
||||
} else {
|
||||
// Search for a new focus target
|
||||
DisplayContent displayContent = mRoot.getDisplayContent(displayId);
|
||||
@@ -8554,18 +8575,18 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (newFocusTarget == null) {
|
||||
ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus remove request for "
|
||||
+ "win=%s dropped since no candidate was found",
|
||||
embeddedWindow.getName());
|
||||
embeddedWindow);
|
||||
return;
|
||||
}
|
||||
t.requestFocusTransfer(newFocusTarget.mInputChannelToken, newFocusTarget.getName(),
|
||||
inputToken, embeddedWindow.getName(),
|
||||
inputToken, embeddedWindow.toString(),
|
||||
displayId).apply();
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Transfer focus request " + newFocusTarget,
|
||||
"reason=grantEmbeddedWindowFocus(false)");
|
||||
}
|
||||
ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
|
||||
embeddedWindow.getName(), grantFocus);
|
||||
embeddedWindow, grantFocus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8594,24 +8615,24 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
SurfaceControl.Transaction t = mTransactionFactory.get();
|
||||
if (grantFocus) {
|
||||
t.requestFocusTransfer(targetInputToken, embeddedWindow.getName(),
|
||||
t.requestFocusTransfer(targetInputToken, embeddedWindow.toString(),
|
||||
hostWindow.mInputChannel.getToken(),
|
||||
hostWindow.getName(),
|
||||
hostWindow.getDisplayId()).apply();
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Transfer focus request " + embeddedWindow.getName(),
|
||||
"Transfer focus request " + embeddedWindow,
|
||||
"reason=grantEmbeddedWindowFocus(true)");
|
||||
} else {
|
||||
t.requestFocusTransfer(hostWindow.mInputChannel.getToken(), hostWindow.getName(),
|
||||
targetInputToken,
|
||||
embeddedWindow.getName(),
|
||||
embeddedWindow.toString(),
|
||||
hostWindow.getDisplayId()).apply();
|
||||
EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
|
||||
"Transfer focus request " + hostWindow,
|
||||
"reason=grantEmbeddedWindowFocus(false)");
|
||||
}
|
||||
ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
|
||||
embeddedWindow.getName(), grantFocus);
|
||||
embeddedWindow, grantFocus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ import java.util.function.Predicate;
|
||||
|
||||
/** A window in the window manager. */
|
||||
class WindowState extends WindowContainer<WindowState> implements WindowManagerPolicy.WindowState,
|
||||
InsetsControlTarget {
|
||||
InsetsControlTarget, InputTarget {
|
||||
static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
|
||||
|
||||
// The minimal size of a window within the usable area of the freeform root task.
|
||||
@@ -1727,7 +1727,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return state;
|
||||
}
|
||||
|
||||
int getDisplayId() {
|
||||
@Override
|
||||
public int getDisplayId() {
|
||||
final DisplayContent displayContent = getDisplayContent();
|
||||
if (displayContent == null) {
|
||||
return Display.INVALID_DISPLAY;
|
||||
@@ -1735,6 +1736,21 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
return displayContent.getDisplayId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindowState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWindow getIWindow() {
|
||||
return mClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPid() {
|
||||
return mSession.mPid;
|
||||
}
|
||||
|
||||
Task getTask() {
|
||||
return mActivityRecord != null ? mActivityRecord.getTask() : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user