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

Commit 6636ea6d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Allow adding EmbeddedWindows without host windows"

parents 7e5a2369 ddbd2510
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -103,8 +103,7 @@ class WindowlessWindowManager implements IWindowSession {
        }

        if (((attrs.inputFeatures &
                WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) &&
                (mHostInputToken != null)) {
                WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0)) {
            try {
                mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, outInputChannel);
            } catch (RemoteException e) {
+28 −16
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package com.android.server.wm;

import static com.android.server.wm.ActivityRecord.INVALID_PID;

import android.annotation.Nullable;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
@@ -39,8 +39,21 @@ class EmbeddedWindowController {
        mWmLock = wmLock;
    }

    void add(IBinder inputToken, IWindow window, WindowState hostWindowState, int ownerUid,
            int ownerPid) {
    /**
     * Adds a new embedded window.
     *
     * @param inputToken input channel token passed in by the embedding process when it requests
     *                   the server to add an input channel to the embedded surface.
     * @param window     client token used to clean up the map if the embedding process dies
     * @param hostWindowState input channel token belonging to the host window. This is needed to
     *                        handle input callbacks to wm. It's used when raising ANR and when
     *                        the user taps out side of the focused region on screen. This can be
     *                        null if there is no host window.
     * @param ownerUid  calling uid
     * @param ownerPid  calling pid used for anr blaming
     */
    void add(IBinder inputToken, IWindow window, @Nullable WindowState hostWindowState,
            int ownerUid, int ownerPid) {
        EmbeddedWindow embeddedWindow = new EmbeddedWindow(window, hostWindowState, ownerUid,
                ownerPid);
        try {
@@ -61,31 +74,30 @@ class EmbeddedWindowController {
        return embeddedWindow != null ? embeddedWindow.mHostWindowState : null;
    }

    int getOwnerPid(IBinder inputToken) {
        EmbeddedWindow embeddedWindow = mWindows.get(inputToken);
        return embeddedWindow != null ? embeddedWindow.mOwnerPid : INVALID_PID;
    }

    void remove(IWindow client) {
        for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
            if (entry.getValue().mClient.asBinder() == client.asBinder()) {
                mWindows.remove(entry.getKey());
        for (int i = mWindows.size() - 1; i >= 0; i--) {
            if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) {
                mWindows.removeAt(i);
                return;
            }
        }
    }

    void removeWindowsWithHost(WindowState host) {
        for (ArrayMap.Entry<IBinder, EmbeddedWindow> entry: mWindows.entrySet()) {
            if (entry.getValue().mHostWindowState == host) {
                mWindows.remove(entry.getKey());
        for (int i = mWindows.size() - 1; i >= 0; i--) {
            if (mWindows.valueAt(i).mHostWindowState == host) {
                mWindows.removeAt(i);
            }
        }
    }

    private static class EmbeddedWindow {
    EmbeddedWindow get(IBinder inputToken) {
        return mWindows.get(inputToken);
    }

    static class EmbeddedWindow {
        final IWindow mClient;
        final WindowState mHostWindowState;
        @Nullable final WindowState mHostWindowState;
        final int mOwnerUid;
        final int mOwnerPid;

+26 −10
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.view.KeyEvent;
import android.view.WindowManager;

import com.android.server.input.InputManagerService;
import com.android.server.wm.EmbeddedWindowController.EmbeddedWindow;

import java.io.PrintWriter;
import java.util.concurrent.atomic.AtomicReference;
@@ -90,20 +91,39 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
        int windowPid = INVALID_PID;
        //TODO(b/141764879) Limit scope of wm lock when input calls notifyANR
        synchronized (mService.mGlobalLock) {

            // Check if we can blame a window
            if (token != null) {
                windowState = mService.mInputToWindowMap.get(token);
                if (windowState != null) {
                    activity = windowState.mActivityRecord;
                    windowPid = windowState.mSession.mPid;
                    // Figure out whether this window is layered above system windows.
                    // We need to do this here to help the activity manager know how to
                    // layer its ANR dialog.
                    aboveSystem = isWindowAboveSystem(windowState);
                }
            }

            // Check if we can blame an embedded window
            if (token != null && windowState == null) {
                EmbeddedWindow embeddedWindow = mService.mEmbeddedWindowController.get(token);
                if (embeddedWindow != null) {
                    windowPid = embeddedWindow.mOwnerPid;
                    WindowState hostWindowState = embeddedWindow.mHostWindowState;
                    if (hostWindowState == null) {
                        // The embedded window has no host window and we cannot easily determine
                        // its z order. Try to place the anr dialog as high as possible.
                        aboveSystem = true;
                    } else {
                    // Check if this is an embedded window and if so get the embedded app pid
                    windowPid = mService.mEmbeddedWindowController.getOwnerPid(token);
                    WindowState hostWindowState =
                            mService.mEmbeddedWindowController.getHostWindow(token);
                        aboveSystem = isWindowAboveSystem(hostWindowState);
                    }
                }
            }

            // Check if we can blame an activity. If we don't have an activity to blame, pull out
            // the token passed in via input application handle. This can happen if there are no
            // focused windows but input dispatcher knows the focused app.
            if (activity == null && inputApplicationHandle != null) {
                activity = ActivityRecord.forTokenLocked(inputApplicationHandle.token);
            }
@@ -112,10 +132,6 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
                Slog.i(TAG_WM, "Input event dispatching timed out "
                        + "sending to " + windowState.mAttrs.getTitle()
                        + ".  Reason: " + reason);
                // Figure out whether this window is layered above system windows.
                // We need to do this here to help the activity manager know how to
                // layer its ANR dialog.
                aboveSystem = isWindowAboveSystem(windowState);
            } else if (activity != null) {
                Slog.i(TAG_WM, "Input event dispatching timed out "
                        + "sending to application " + activity.stringName
+7 −0
Original line number Diff line number Diff line
@@ -621,8 +621,15 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
        return false;
    }

    @Override
    public void grantInputChannel(int displayId, SurfaceControl surface,
            IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
        if (hostInputToken == null && !mCanAddInternalSystemWindow) {
            // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to
            // embedded windows without providing a host window input token
            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            mService.grantInputChannel(mUid, mPid, displayId, surface, window,
+8 −8
Original line number Diff line number Diff line
@@ -7674,19 +7674,17 @@ public class WindowManagerService extends IWindowManager.Stub
     */
    void grantInputChannel(int callingUid, int callingPid, int displayId, SurfaceControl surface,
            IWindow window, IBinder hostInputToken, InputChannel outInputChannel) {
        final InputApplicationHandle applicationHandle;
        InputApplicationHandle applicationHandle = null;
        final String name;
        final InputChannel[] inputChannels;
        final InputChannel clientChannel;
        final InputChannel serverChannel;
        synchronized (mGlobalLock) {
            final WindowState hostWindow = mInputToWindowMap.get(hostInputToken);
            if (hostWindow == null) {
                Slog.e(TAG, "Failed to grant input channel");
                return;
            }
            final String hostWindowName = (hostWindow != null)
                    ? hostWindow.getWindowTag().toString() : "Internal";
            name = "EmbeddedWindow{ u" + UserHandle.getUserId(callingUid)
                    + " " + hostWindow.getWindowTag() + "}";
                    + " " + hostWindowName + "}";

            inputChannels = InputChannel.openInputChannelPair(name);
            serverChannel = inputChannels[0];
@@ -7694,9 +7692,11 @@ public class WindowManagerService extends IWindowManager.Stub
            mInputManager.registerInputChannel(serverChannel);
            mEmbeddedWindowController.add(serverChannel.getToken(), window, hostWindow, callingUid,
                    callingPid);
            if (hostWindow != null) {
                applicationHandle = new InputApplicationHandle(
                        hostWindow.mInputWindowHandle.inputApplicationHandle);
            }
        }

        clientChannel.transferTo(outInputChannel);
        clientChannel.dispose();