diff options
| author | 2020-08-15 15:03:46 -0700 | |
|---|---|---|
| committer | 2020-08-26 10:30:39 -0700 | |
| commit | 904ea677246eafc20a44537eb81a99bbcc0acc17 (patch) | |
| tree | 96467725271c0cb56d3c9b0b31663d9062cb7198 | |
| parent | b0e58545c11ee1ad5b5277428ebb0f98069f0318 (diff) | |
Misc clean up before requesting focus via setFocusedWindow api
Replace focus changed callback to use the callback from InputDispatcher.
Currently the system posts a message and informs accessibility services,
window focus observers and window change listeners. With the exception
of accessibility service (which requires to be notified before the
client gets notified), the other callbacks should be synchronized with
the callback from InputDispatcher.
This change also cleans up null checks for ActivityRecord#appToken
since it cannot be null.
Test: presubmit
Bug: 151179149
Change-Id: Id79553835048c090505589d62dee9cb8f38f23ff
11 files changed, 150 insertions, 182 deletions
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 75eb7b64a444..a2a2216028ac 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -325,12 +325,6 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, - "-1587841219": { - "message": "Focus moving from %s to %s displayId=%d", - "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-1568331821": { "message": "Enabling listeners", "level": "VERBOSE", @@ -415,6 +409,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "-1438175584": { + "message": "Input focus has changed to %s display=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" + }, "-1434147454": { "message": "cleanupAnimation(): Notify animation finished mPendingAnimations=%d reorderMode=%d", "level": "DEBUG", @@ -565,6 +565,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowStateAnimator.java" }, + "-1142279614": { + "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, "-1130891072": { "message": "Orientation continue waiting for draw in %s", "level": "VERBOSE", @@ -799,12 +805,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-771282525": { - "message": "Losing focus: %s", - "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-771177730": { "message": "Removing focused app token:%s displayId=%d", "level": "VERBOSE", @@ -847,12 +847,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DragState.java" }, - "-687185281": { - "message": "New topFocusedDisplayId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/RootWindowContainer.java" - }, "-668956537": { "message": " THUMBNAIL %s: CREATE", "level": "INFO", @@ -877,6 +871,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowToken.java" }, + "-639217716": { + "message": "setFocusedApp %s displayId=%d Callers=%s", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, "-635082269": { "message": "******** booted=%b msg=%b haveBoot=%b haveApp=%b haveWall=%b wallEnabled=%b haveKeyguard=%b", "level": "INFO", @@ -895,12 +895,6 @@ "group": "WM_DEBUG_BOOT", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-603199586": { - "message": "Clearing focused app, displayId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "-593535526": { "message": "Binding proc %s with config %s", "level": "VERBOSE", @@ -919,6 +913,12 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/DisplayRotation.java" }, + "-561092364": { + "message": "onPointerDownOutsideFocusLocked called on %s", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "-549028919": { "message": "enableScreenIfNeededLocked: mDisplayEnabled=%b mForceDisplayEnabled=%b mShowingBootMessages=%b mSystemBooted=%b. %s", "level": "INFO", @@ -1201,12 +1201,6 @@ "group": "WM_DEBUG_RECENTS_ANIMATIONS", "at": "com\/android\/server\/wm\/RecentsAnimation.java" }, - "-96848838": { - "message": "Gaining focus: %s", - "level": "INFO", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "-90559682": { "message": "Config is skipping already pausing %s", "level": "VERBOSE", @@ -1363,6 +1357,12 @@ "group": "WM_DEBUG_STARTING_WINDOW", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "115358443": { + "message": "Focus changing: %s -> %s", + "level": "INFO", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/WindowManagerService.java" + }, "123161180": { "message": "SEVER CHILDREN", "level": "INFO", @@ -1495,12 +1495,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", "at": "com\/android\/server\/wm\/AppTransition.java" }, - "285317231": { - "message": "Input focus has changed to %s", - "level": "DEBUG", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/InputMonitor.java" - }, "288485303": { "message": "Attempted to set remove mode to a display that does not exist: %d", "level": "WARN", @@ -1537,6 +1531,12 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowSurfaceController.java" }, + "312030608": { + "message": "New topFocusedDisplayId=%d", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/RootWindowContainer.java" + }, "315395835": { "message": "Trying to add window with invalid user=%d", "level": "WARN", @@ -1699,12 +1699,6 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/WindowSurfaceController.java" }, - "584499099": { - "message": "Set focused app to: %s moveFocusNow=%b displayId=%d", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "585096182": { "message": "SURFACE isColorSpaceAgnostic=%b: %s", "level": "INFO", @@ -1747,6 +1741,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "620519522": { + "message": "findFocusedWindow: No focusable windows, display=%d", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, "628276090": { "message": "Delaying app transition for screen rotation animation to finish", "level": "VERBOSE", @@ -1903,6 +1903,12 @@ "group": "WM_DEBUG_ADD_REMOVE", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, + "872933199": { + "message": "Changing focus from %s to %s displayId=%d Callers=%s", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, "873914452": { "message": "goodToGo()", "level": "DEBUG", @@ -2137,12 +2143,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/ScreenRotationAnimation.java" }, - "1358462645": { - "message": "Looking for focus: %s, flags=%d, canReceive=%b", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "1360551978": { "message": "Trying to update display configuration for non-existing displayId=%d", "level": "WARN", @@ -2233,12 +2233,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, - "1469292670": { - "message": "Changing focus from %s to %s displayId=%d Callers=%s", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "1495525537": { "message": "createWallpaperAnimations()", "level": "DEBUG", @@ -2677,12 +2671,6 @@ "group": "WM_DEBUG_IME", "at": "com\/android\/server\/wm\/DisplayContent.java" }, - "2128604122": { - "message": "findFocusedWindow: No focusable windows.", - "level": "VERBOSE", - "group": "WM_DEBUG_FOCUS_LIGHT", - "at": "com\/android\/server\/wm\/DisplayContent.java" - }, "2128917433": { "message": "onProposedRotationChanged, rotation=%d", "level": "VERBOSE", diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 56261c4fce97..7d4d5629dacd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -401,7 +401,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final ActivityTaskManagerService mAtmService; final ActivityInfo info; // activity info provided by developer in AndroidManifest - // Non-null only for application tokens. // TODO: rename to mActivityToken final ActivityRecord.Token appToken; // Which user is this running for? @@ -5480,10 +5479,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void updateReportedVisibilityLocked() { - if (appToken == null) { - return; - } - if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this); final int count = mChildren.size(); @@ -6330,8 +6325,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) { - final IBinder binder = - (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null; + final IBinder binder = freezeScreenIfNeeded ? appToken.asBinder() : null; setOrientation(requestedOrientation, binder, this); // Push the new configuration to the requested app in case where it's not pushed, e.g. when @@ -7713,9 +7707,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void writeNameToProto(ProtoOutputStream proto, long fieldId) { - if (appToken != null) { - proto.write(fieldId, appToken.getName()); - } + proto.write(fieldId, appToken.getName()); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 6a8cbfbb5840..c58b5b50d508 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -125,6 +125,7 @@ import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.wm.Task.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.wm.WindowContainer.POSITION_TOP; +import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import android.Manifest; import android.annotation.IntDef; @@ -5465,8 +5466,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { updateResumedAppTrace(r); mLastResumedActivity = r; - r.getDisplay().setFocusedApp(r, true); - + final boolean changed = r.getDisplay().setFocusedApp(r); + if (changed) { + mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, + true /*updateInputWindows*/); + } if (prevTask == null || task != prevTask) { if (prevTask != null) { mTaskChangeNotificationController.notifyTaskFocusChanged(prevTask.mTaskId, false); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 2f7cc69b01a7..aa8069a76330 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -115,13 +115,11 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIG import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static com.android.server.wm.WindowManagerService.H.REPORT_FOCUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.REPORT_HARD_KEYBOARD_STATUS_CHANGE; import static com.android.server.wm.WindowManagerService.H.UPDATE_MULTI_WINDOW_STACKS; import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT; import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD; import static com.android.server.wm.WindowManagerService.SEAMLESS_ROTATION_TIMEOUT_DURATION; -import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_REMOVING_FOCUS; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_ASSIGN_LAYERS; @@ -649,8 +647,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> { final ActivityRecord focusedApp = mFocusedApp; - ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b", - w, w.mAttrs.flags, w.canReceiveKeys()); + ProtoLog.v(WM_DEBUG_FOCUS, "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s", + w, w.mAttrs.flags, w.canReceiveKeys(), + w.canReceiveKeysReason(false /* fromUserTouch */)); if (!w.canReceiveKeys()) { return false; @@ -3072,7 +3071,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ WindowState findFocusedWindowIfNeeded(int topFocusedDisplayId) { return (mWmService.mPerDisplayFocusEnabled || topFocusedDisplayId == INVALID_DISPLAY) - ? findFocusedWindow() : null; + ? findFocusedWindow() : null; } WindowState findFocusedWindow() { @@ -3081,7 +3080,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */); if (mTmpWindow == null) { - ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows."); + ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "findFocusedWindow: No focusable windows, display=%d", + getDisplayId()); return null; } return mTmpWindow; @@ -3116,18 +3116,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp && mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) { assignWindowLayers(false /* setLayoutNeeded */); } - } - if (imWindowChanged) { - mWmService.mWindowsChanged = true; - setLayoutNeeded(); - newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); - } - if (mCurrentFocus != newFocus) { - mWmService.mH.obtainMessage(REPORT_FOCUS_CHANGE, this).sendToTarget(); + if (imWindowChanged) { + mWmService.mWindowsChanged = true; + setLayoutNeeded(); + newFocus = findFocusedWindowIfNeeded(topFocusedDisplayId); + } } - ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s", + ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Changing focus from %s to %s displayId=%d Callers=%s", mCurrentFocus, newFocus, getDisplayId(), Debug.getCallers(4)); final WindowState oldFocus = mCurrentFocus; mCurrentFocus = newFocus; @@ -3185,9 +3182,25 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (mode == UPDATE_FOCUS_PLACING_SURFACES) { pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM; } + + // Notify the accessibility manager for the change so it has the windows before the newly + // focused one starts firing events. + // TODO(b/151179149) investigate what info accessibility service needs before input can + // dispatch focus to clients. + if (mWmService.mAccessibilityController != null) { + mWmService.mH.sendMessage(PooledLambda.obtainMessage( + this::updateAccessibilityOnWindowFocusChanged, + mWmService.mAccessibilityController)); + } + + mLastFocus = mCurrentFocus; return true; } + void updateAccessibilityOnWindowFocusChanged(AccessibilityController accessibilityController) { + accessibilityController.onWindowFocusChangedNotLocked(getDisplayId()); + } + private static void onWindowFocusChanged(WindowState oldFocus, WindowState newFocus) { final Task focusedTask = newFocus != null ? newFocus.getTask() : null; final Task unfocusedTask = oldFocus != null ? oldFocus.getTask() : null; @@ -3219,6 +3232,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (mFocusedApp == newFocus) { return false; } + ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "setFocusedApp %s displayId=%d Callers=%s", + newFocus, getDisplayId(), Debug.getCallers(4)); mFocusedApp = newFocus; getInputMonitor().setFocusedAppLw(newFocus); updateTouchExcludeRegion(); @@ -4708,7 +4723,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // Traverse all windows top down to assemble the gesture exclusion rects. // For each window, we only take the rects that fall within its touchable region. forAllWindows(w -> { - if (w.cantReceiveTouchInput() || !w.isVisible() + if (!w.canReceiveTouchInput() || !w.isVisible() || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0 || unhandled.isEmpty()) { return; @@ -5225,30 +5240,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp && (mAtmService.mRunningVoice == null); } - void setFocusedApp(ActivityRecord r, boolean moveFocusNow) { - final ActivityRecord newFocus; - final IBinder token = r.appToken; - if (token == null) { - ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d", - mDisplayId); - newFocus = null; - } else { - newFocus = mWmService.mRoot.getActivityRecord(token); - if (newFocus == null) { - Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token - + ", displayId=" + mDisplayId); - } - ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, - "Set focused app to: %s moveFocusNow=%b displayId=%d", newFocus, - moveFocusNow, mDisplayId); - } - - final boolean changed = setFocusedApp(newFocus); - if (moveFocusNow && changed) { - mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, - true /*updateInputWindows*/); - } - } void ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java index 999aab982816..ec62ed44c640 100644 --- a/services/core/java/com/android/server/wm/DragDropController.java +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -114,7 +114,7 @@ class DragDropController { final WindowState callingWin = mService.windowForClientLocked( null, window, false); - if (callingWin == null || callingWin.cantReceiveTouchInput()) { + if (callingWin == null || !callingWin.canReceiveTouchInput()) { Slog.w(TAG_WM, "Bad requesting window " + window); return null; // !!! TODO: throw here? } diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java index e166bfc08ad4..0978636ea502 100644 --- a/services/core/java/com/android/server/wm/InputManagerCallback.java +++ b/services/core/java/com/android/server/wm/InputManagerCallback.java @@ -24,6 +24,7 @@ import android.view.InputApplicationHandle; import android.view.KeyEvent; import android.view.WindowManager; +import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.am.ActivityManagerService; import com.android.server.input.InputManagerService; import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow; @@ -252,7 +253,7 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal // All the calls below need to happen without the WM lock held since they call into AM. mService.mAtmInternal.saveANRState(reason); - if (activity != null && activity.appToken != null) { + if (activity != null) { // Notify the activity manager about the timeout and let it decide whether // to abort dispatching or keep waiting. final boolean abort = activity.keyDispatchingTimedOut(reason, windowPid); @@ -410,6 +411,8 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal requestRefreshConfiguration = dispatchPointerCaptureChanged(focusedWindow, false); } mFocusedWindow.set(newFocusedWindow); + mService.mH.sendMessage(PooledLambda.obtainMessage(mService::reportFocusChanged, + oldToken, newToken)); return requestRefreshConfiguration; } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index fb511e032c98..4efd687b7bb4 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -370,7 +370,8 @@ final class InputMonitor { * Layer assignment is assumed to be complete by the time this is called. */ public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) { - ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s", newWindow); + ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Input focus has changed to %s display=%d", + newWindow, mDisplayId); if (newWindow != mInputFocus) { if (newWindow != null && newWindow.canReceiveKeys()) { @@ -493,7 +494,7 @@ final class InputMonitor { final int type = w.mAttrs.type; final boolean isVisible = w.isVisibleLw(); if (inputChannel == null || inputWindowHandle == null || w.mRemoved - || (w.cantReceiveTouchInput() && !shouldApplyRecentsInputConsumer)) { + || (!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. diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 21e30ce0a495..f9e6270aec5d 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -40,7 +40,6 @@ import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; import static android.view.WindowManager.TRANSIT_TASK_TO_BACK; - import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; @@ -90,7 +89,6 @@ import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREEN import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING; - import static java.lang.Integer.MAX_VALUE; import android.annotation.IntDef; @@ -129,6 +127,7 @@ import android.os.UserHandle; import android.os.storage.StorageManager; import android.provider.Settings; import android.service.voice.IVoiceInteractionSession; +import android.util.ArrayMap; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.IntArray; @@ -162,7 +161,6 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Set; @@ -214,7 +212,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> private int mTopFocusedDisplayId = INVALID_DISPLAY; // Map from the PID to the top most app which has a focused window of the process. - final HashMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new HashMap<>(); + final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>(); // Only a separate transaction until we separate the apply surface changes // transaction from the global transaction. @@ -480,8 +478,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mTopFocusedDisplayId = topFocusedDisplayId; mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId); mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId); - ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", - topFocusedDisplayId); + ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId); } return changed; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index c45ccb6e17e3..19179a808d7c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -376,8 +376,11 @@ public class WindowManagerService extends IWindowManager.Stub private static final String BOOT_ANIMATION_SERVICE = "bootanim"; static final int UPDATE_FOCUS_NORMAL = 0; + /** Caller will assign layers */ static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; + /** Caller is performing surface placement */ static final int UPDATE_FOCUS_PLACING_SURFACES = 2; + /** Caller will performSurfacePlacement */ static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3; /** Indicates we are removing the focused window when updating the focus. */ static final int UPDATE_FOCUS_REMOVING_FOCUS = 4; @@ -4730,12 +4733,30 @@ public class WindowManagerService extends IWindowManager.Stub return false; } + 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); + } + + if (newFocus != null) { + newFocus.reportFocusChangedSerialized(true); + notifyFocusChanged(); + } + + if (lastFocus != null) { + lastFocus.reportFocusChangedSerialized(false); + } + } + // ------------------------------------------------------------- // Async Handler // ------------------------------------------------------------- final class H extends android.os.Handler { - public static final int REPORT_FOCUS_CHANGE = 2; public static final int WINDOW_FREEZE_TIMEOUT = 11; public static final int PERSIST_ANIMATION_SCALE = 14; @@ -4788,50 +4809,6 @@ public class WindowManagerService extends IWindowManager.Stub Slog.v(TAG_WM, "handleMessage: entry what=" + msg.what); } switch (msg.what) { - case REPORT_FOCUS_CHANGE: { - final DisplayContent displayContent = (DisplayContent) msg.obj; - WindowState lastFocus; - WindowState newFocus; - - AccessibilityController accessibilityController = null; - - synchronized (mGlobalLock) { - if (mAccessibilityController != null) { - accessibilityController = mAccessibilityController; - } - - lastFocus = displayContent.mLastFocus; - newFocus = displayContent.mCurrentFocus; - if (lastFocus == newFocus) { - // Focus is not changing, so nothing to do. - return; - } - displayContent.mLastFocus = newFocus; - ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Focus moving from %s" - + " to %s displayId=%d", lastFocus, newFocus, - displayContent.getDisplayId()); - } - - // First notify the accessibility manager for the change so it has - // the windows before the newly focused one starts firing events. - if (accessibilityController != null) { - accessibilityController.onWindowFocusChangedNotLocked( - displayContent.getDisplayId()); - } - - if (newFocus != null) { - ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Gaining focus: %s", newFocus); - newFocus.reportFocusChangedSerialized(true); - notifyFocusChanged(); - } - - if (lastFocus != null) { - ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "Losing focus: %s", lastFocus); - lastFocus.reportFocusChangedSerialized(false); - } - break; - } - case WINDOW_FREEZE_TIMEOUT: { final DisplayContent displayContent = (DisplayContent) msg.obj; synchronized (mGlobalLock) { @@ -7994,6 +7971,8 @@ public class WindowManagerService extends IWindowManager.Stub return; } + ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "onPointerDownOutsideFocusLocked called on %s", + touchedWindow); final DisplayContent displayContent = touchedWindow.getDisplayContent(); if (!displayContent.isOnTop()) { displayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP, displayContent, @@ -8022,10 +8001,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - try { - mActivityTaskManager.setFocusedTask(task.mTaskId); - } catch (RemoteException e) { - } + mAtmService.setFocusedTask(task.mTaskId); } /** diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 9ff33b18cb89..84a9c750d2d3 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2884,12 +2884,25 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return canReceiveKeys(false /* fromUserTouch */); } + public String canReceiveKeysReason(boolean fromUserTouch) { + return "fromTouch= " + fromUserTouch + + " isVisibleOrAdding=" + isVisibleOrAdding() + + " mViewVisibility=" + mViewVisibility + + " mRemoveOnExit=" + mRemoveOnExit + + " flags=" + mAttrs.flags + + " appWindowsAreFocusable=" + + (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch)) + + " canReceiveTouchInput=" + canReceiveTouchInput() + + " displayIsOnTop=" + getDisplayContent().isOnTop() + + " displayIsTrusted=" + getDisplayContent().isTrusted(); + } + public boolean canReceiveKeys(boolean fromUserTouch) { final boolean canReceiveKeys = isVisibleOrAdding() && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0) && (mActivityRecord == null || mActivityRecord.windowsAreFocusable(fromUserTouch)) - && !cantReceiveTouchInput(); + && canReceiveTouchInput(); if (!canReceiveKeys) { return false; } @@ -2907,15 +2920,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return showBecauseOfActivity || showBecauseOfWindow; } - /** @return {@code false} if this window desires touch events. */ - boolean cantReceiveTouchInput() { - if (mActivityRecord == null || mActivityRecord.getTask() == null) { - return false; + /** + * @return {@code true} if this window can receive touches based on among other things, + * windowing state and recents animation state. + **/ + boolean canReceiveTouchInput() { + if (mActivityRecord == null || mActivityRecord.getTask() == null) { + return true; } - return mActivityRecord.getTask().getRootTask().shouldIgnoreInput() - || !mActivityRecord.mVisibleRequested - || isRecentsAnimationConsumingAppInput(); + return !mActivityRecord.getTask().getRootTask().shouldIgnoreInput() + && mActivityRecord.mVisibleRequested + && !isRecentsAnimationConsumingAppInput(); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 9603d28c286b..3106ca26c8a1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -661,14 +661,14 @@ public class WindowStateTests extends WindowTestsBase { RecentsAnimationController recentsController = mock(RecentsAnimationController.class); when(recentsController.shouldApplyInputConsumer(win0.mActivityRecord)).thenReturn(true); mWm.setRecentsAnimationController(recentsController); - assertTrue(win0.cantReceiveTouchInput()); + assertFalse(win0.canReceiveTouchInput()); } @Test public void testCantReceiveTouchWhenAppTokenHiddenRequested() { final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0"); win0.mActivityRecord.mVisibleRequested = false; - assertTrue(win0.cantReceiveTouchInput()); + assertFalse(win0.canReceiveTouchInput()); } @Test @@ -676,7 +676,7 @@ public class WindowStateTests extends WindowTestsBase { final WindowState win0 = createWindow(null, TYPE_APPLICATION, "win0"); win0.mActivityRecord.getStack().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); win0.mActivityRecord.getStack().setFocusable(false); - assertTrue(win0.cantReceiveTouchInput()); + assertFalse(win0.canReceiveTouchInput()); } @UseTestDisplay(addWindows = W_ACTIVITY) |