Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 179b1e22 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

WM: Track focus changes in AccessibilityController

Forward focus changes from input and tracks them
in AccessibilityController. This will help track embedded window
focus changes as well and rely on input as the source of truth
for focus. Accessibility service will start querying the controller
for focus changes.

Bug: b/188792659
Test: presubmit
Test: test talkback
Change-Id: I21a6f1a7353844d2b0f59f32e802ed1f0a3d66ff
Merged-In: I21a6f1a7353844d2b0f59f32e802ed1f0a3d66ff
parent ecdb3cdb
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -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.
     */
+17 −27
Original line number Diff line number Diff line
@@ -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) {
            InputTarget target = mService.getInputTargetFromToken(inputToken);
            if (target == 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.
            }

            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");
            InputTarget target = mService.getInputTargetFromToken(inputToken);
            if (target == null) {
                Slog.e(TAG_WM, "Unknown token, dropping notifyWindowConnectionResponsive request");
                return;
            }
                pid = embeddedWindow.mOwnerPid;
            }
            pid = target.getPid();
        }
        mService.mAmInternal.inputDispatchingResumed(pid);
    }
+1 −0
Original line number Diff line number Diff line
@@ -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;
        }
+24 −3
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * 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();
}
Loading