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

Commit 7675c61e authored by Charles Chen's avatar Charles Chen Committed by Android (Google) Code Review
Browse files

Merge "Creates WindowToken for WindowContext"

parents d14dcb33 8cb66757
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -2887,6 +2887,12 @@
      "group": "WM_DEBUG_ORIENTATION",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "1252594551": {
      "message": "Window types in WindowContext and LayoutParams.type should match! Type from LayoutParams is %d, but type from WindowContext is %d",
      "level": "WARN",
      "group": "WM_ERROR",
      "at": "com\/android\/server\/wm\/WindowManagerService.java"
    },
    "1254403969": {
      "message": "Surface returned was null: %s",
      "level": "VERBOSE",
+5 −0
Original line number Diff line number Diff line
@@ -3049,6 +3049,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        return null;
    }

    /** Cheap way of doing cast and instanceof. */
    WindowToken asWindowToken() {
        return null;
    }

    /** Cheap way of doing cast and instanceof. */
    ActivityRecord asActivityRecord() {
        return null;
+62 −5
Original line number Diff line number Diff line
@@ -17,23 +17,26 @@
package com.android.server.wm;

import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.IWindowToken;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.view.View;
import android.view.WindowManager.LayoutParams.WindowType;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;

import java.util.Map;
import java.util.Objects;

/**
@@ -61,7 +64,7 @@ import java.util.Objects;
 */
class WindowContextListenerController {
    @VisibleForTesting
    final Map<IBinder, WindowContextListenerImpl> mListeners = new ArrayMap<>();
    final ArrayMap<IBinder, WindowContextListenerImpl> mListeners = new ArrayMap<>();

    /**
     * Registers the listener to a {@code container} which is associated with
@@ -73,12 +76,16 @@ class WindowContextListenerController {
     * @param clientToken the token to associate with the listener
     * @param container the {@link WindowContainer} which the listener is going to listen to.
     * @param ownerUid the caller UID
     * @param type the window type
     * @param options a bundle used to pass window-related options.
     */
    void registerWindowContainerListener(@NonNull IBinder clientToken,
            @NonNull WindowContainer container, int ownerUid) {
            @NonNull WindowContainer container, int ownerUid, @WindowType int type,
            @Nullable Bundle options) {
        WindowContextListenerImpl listener = mListeners.get(clientToken);
        if (listener == null) {
            listener = new WindowContextListenerImpl(clientToken, container, ownerUid);
            listener = new WindowContextListenerImpl(clientToken, container, ownerUid, type,
                    options);
            listener.register();
        } else {
            listener.updateContainer(container);
@@ -113,11 +120,53 @@ class WindowContextListenerController {
        return true;
    }

    boolean hasListener(IBinder clientToken) {
        return mListeners.containsKey(clientToken);
    }

    @WindowType int getWindowType(IBinder clientToken) {
        final WindowContextListenerImpl listener = mListeners.get(clientToken);
        return listener != null ? listener.mType : INVALID_WINDOW_TYPE;
    }

    @Nullable Bundle getOptions(IBinder clientToken) {
        final WindowContextListenerImpl listener = mListeners.get(clientToken);
        return listener != null ? listener.mOptions : null;
    }

    @Nullable WindowContainer getContainer(IBinder clientToken) {
        final WindowContextListenerImpl listener = mListeners.get(clientToken);
        return listener != null ? listener.mContainer : null;
    }

    @Override
    public String toString() {
        final StringBuilder builder = new StringBuilder("WindowContextListenerController{");
        builder.append("mListeners=[");

        final int size = mListeners.values().size();
        for (int i = 0; i < size; i++) {
            builder.append(mListeners.valueAt(i));
            if (i != size - 1) {
                builder.append(", ");
            }
        }
        builder.append("]}");
        return builder.toString();
    }

    @VisibleForTesting
    class WindowContextListenerImpl implements WindowContainerListener {
        @NonNull private final IBinder mClientToken;
        private final int mOwnerUid;
        @NonNull private WindowContainer mContainer;
        /**
         * The options from {@link Context#createWindowContext(int, Bundle)}.
         * <p>It can be used for choosing the {@link DisplayArea} where the window context
         * is located. </p>
         */
        @Nullable private final Bundle mOptions;
        @WindowType private final int mType;

        private DeathRecipient mDeathRecipient;

@@ -125,10 +174,12 @@ class WindowContextListenerController {
        private Configuration mLastReportedConfig;

        private WindowContextListenerImpl(IBinder clientToken, WindowContainer container,
                int ownerUid) {
                int ownerUid, @WindowType int type, @Nullable Bundle options) {
            mClientToken = clientToken;
            mContainer = Objects.requireNonNull(container);
            mOwnerUid = ownerUid;
            mType = type;
            mOptions = options;

            final DeathRecipient deathRecipient = new DeathRecipient();
            try {
@@ -226,6 +277,12 @@ class WindowContextListenerController {
            unregister();
        }

        @Override
        public String toString() {
            return "WindowContextListenerImpl{clientToken=" + mClientToken + ", "
                    + "container=" + mContainer + "}";
        }

        private class DeathRecipient implements IBinder.DeathRecipient {
            @Override
            public void binderDied() {
+47 −15
Original line number Diff line number Diff line
@@ -1466,7 +1466,7 @@ public class WindowManagerService extends IWindowManager.Stub
                & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
        int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
                appOp);
        if (res != WindowManagerGlobal.ADD_OKAY) {
        if (res != ADD_OKAY) {
            return res;
        }

@@ -1556,6 +1556,8 @@ public class WindowManagerService extends IWindowManager.Stub

            boolean addToastWindowRequiresToken = false;

            final IBinder windowContextToken = attrs.mWindowContextToken;

            if (token == null) {
                if (!unprivilegedAppCanCreateTokenWith(parentWindow, callingUid, type,
                        rootType, attrs.token, attrs.packageName)) {
@@ -1564,6 +1566,14 @@ public class WindowManagerService extends IWindowManager.Stub
                if (hasParent) {
                    // Use existing parent window token for child windows.
                    token = parentWindow.mToken;
                } else if (mWindowContextListenerController.hasListener(windowContextToken)) {
                    // Respect the window context token if the user provided it.
                    final IBinder binder = attrs.token != null ? attrs.token : windowContextToken;
                    final Bundle options = mWindowContextListenerController
                            .getOptions(windowContextToken);
                    token = new WindowToken(this, binder, type, false /* persistOnEmpty */,
                            displayContent, session.mCanAddInternalSystemWindow, callingUid,
                            isRoundedCornerOverlay, true /* fromClientToken */, options);
                } else {
                    final IBinder binder = attrs.token != null ? attrs.token : client.asBinder();
                    token = new WindowToken(this, binder, type, false, displayContent,
@@ -1632,8 +1642,8 @@ public class WindowManagerService extends IWindowManager.Stub
                // It is not valid to use an app token with other system types; we will
                // instead make a new token for it (as if null had been passed in for the token).
                attrs.token = null;
                token = new WindowToken(this, client.asBinder(), type, false, displayContent,
                        session.mCanAddInternalSystemWindow);
                token = new WindowToken(this, client.asBinder(), type, false /* persistOnEmpty */,
                        displayContent, session.mCanAddInternalSystemWindow);
            }

            final WindowState win = new WindowState(this, session, client, token, parentWindow,
@@ -1657,7 +1667,7 @@ public class WindowManagerService extends IWindowManager.Stub
            win.updateRequestedVisibility(requestedVisibility);

            res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid);
            if (res != WindowManagerGlobal.ADD_OKAY) {
            if (res != ADD_OKAY) {
                return res;
            }

@@ -1688,7 +1698,7 @@ public class WindowManagerService extends IWindowManager.Stub
                // show a focusable toasts while it has focus which will be kept on
                // the screen after the activity goes away.
                if (addToastWindowRequiresToken
                        || (attrs.flags & LayoutParams.FLAG_NOT_FOCUSABLE) == 0
                        || (attrs.flags & FLAG_NOT_FOCUSABLE) == 0
                        || displayContent.mCurrentFocus == null
                        || displayContent.mCurrentFocus.mOwnerUid != callingUid) {
                    mH.sendMessageDelayed(
@@ -1697,9 +1707,26 @@ public class WindowManagerService extends IWindowManager.Stub
                }
            }

            // Switch to listen to the {@link WindowToken token}'s configuration changes when
            // adding a window to the window context.
            if (mWindowContextListenerController.hasListener(windowContextToken)) {
                final int windowContextType = mWindowContextListenerController
                        .getWindowType(windowContextToken);
                if (type != windowContextType) {
                    ProtoLog.w(WM_ERROR, "Window types in WindowContext and"
                            + " LayoutParams.type should match! Type from LayoutParams is %d,"
                            + " but type from WindowContext is %d", type, windowContextType);
                    return WindowManagerGlobal.ADD_INVALID_TYPE;
                }
                final Bundle options = mWindowContextListenerController
                        .getOptions(windowContextToken);
                mWindowContextListenerController.registerWindowContainerListener(
                        windowContextToken, token, callingUid, type, options);
            }

            // From now on, no exceptions or errors allowed!

            res = WindowManagerGlobal.ADD_OKAY;
            res = ADD_OKAY;

            if (mUseBLAST) {
                res |= WindowManagerGlobal.ADD_FLAG_USE_BLAST;
@@ -2763,7 +2790,7 @@ public class WindowManagerService extends IWindowManager.Stub
                final DisplayArea da = dc.getAreaForWindowToken(type, options,
                        callerCanManageAppTokens, false /* roundedCornerOverlay */);
                mWindowContextListenerController.registerWindowContainerListener(clientToken, da,
                        callingUid);
                        callingUid, type, options);
                return true;
            }
        } finally {
@@ -2779,9 +2806,18 @@ public class WindowManagerService extends IWindowManager.Stub
        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (mGlobalLock) {
                if (mWindowContextListenerController.assertCallerCanRemoveListener(clientToken,
                if (!mWindowContextListenerController.assertCallerCanRemoveListener(clientToken,
                        callerCanManageAppTokens, callingUid)) {
                    return;
                }
                final WindowContainer wc = mWindowContextListenerController
                        .getContainer(clientToken);

                mWindowContextListenerController.unregisterWindowContainerListener(clientToken);

                final WindowToken token = wc.asWindowToken();
                if (token != null && token.isFromClient()) {
                    removeWindowToken(token.token, token.getDisplayContent().getDisplayId());
                }
            }
        } finally {
@@ -2792,13 +2828,9 @@ public class WindowManagerService extends IWindowManager.Stub
    @Override
    public boolean isWindowToken(IBinder binder) {
        synchronized (mGlobalLock) {
            final WindowToken windowToken = mRoot.getWindowToken(binder);
            if (windowToken == null) {
                return false;
            }
            // We don't allow activity tokens in WindowContext. TODO(window-context): rename method
            return windowToken.asActivityRecord() == null;
            return mRoot.getWindowToken(binder) != null;
        }

    }

    @Override
+9 −0
Original line number Diff line number Diff line
@@ -820,6 +820,11 @@ class WindowToken extends WindowContainer<WindowState> {
        return toString();
    }

    @Override
    WindowToken asWindowToken() {
        return this;
    }

    /**
     * Return whether windows from this token can layer above the
     * system bars, or in other words extend outside of the "Decor Frame"
@@ -839,4 +844,8 @@ class WindowToken extends WindowContainer<WindowState> {
    int getOwnerUid() {
        return mOwnerUid;
    }

    boolean isFromClient() {
        return mFromClientToken;
    }
}
Loading