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

Commit 746a1d1f authored by Charles Chen's avatar Charles Chen Committed by Automerger Merge Worker
Browse files

Merge "Limit number of window context without any window" into rvc-dev am: 1e52a093

Change-Id: Id6d242168afe4f82158fcd23555e62e4a07accda
parents 88ed8119 1e52a093
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package android.app;

import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;

import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -81,6 +82,11 @@ public class WindowContext extends ContextWrapper {
            mOwnsToken = false;
            throw e.rethrowFromSystemServer();
        }
        if (result == ADD_TOO_MANY_TOKENS) {
            throw new UnsupportedOperationException("createWindowContext failed! Too many unused "
                    + "window contexts. Please see Context#createWindowContext documentation for "
                    + "detail.");
        }
        mOwnsToken = result == ADD_OKAY;
        Reference.reachabilityFence(this);
    }
+9 −1
Original line number Diff line number Diff line
@@ -5812,6 +5812,12 @@ public abstract class Context {
     * display.</b> If there is a need to add different window types, or non-associated windows,
     * separate Contexts should be used.
     * </p>
     * <p>
     * Creating a window context is an expensive operation. Misuse of this API may lead to a huge
     * performance drop. The best practice is to use the same window context when possible.
     * An approach is to create one window context with specific window type and display and
     * use it everywhere it's needed..
     * </p>
     *
     * @param type Window type in {@link WindowManager.LayoutParams}
     * @param options Bundle used to pass window-related options.
@@ -5824,7 +5830,9 @@ public abstract class Context {
     * @see #WINDOW_SERVICE
     * @see #LAYOUT_INFLATER_SERVICE
     * @see #WALLPAPER_SERVICE
     * @throws IllegalArgumentException if token is invalid
     * @throws UnsupportedOperationException if this {@link Context} does not attach to a display or
     * the current number of window contexts without adding any view by
     * {@link WindowManager#addView} <b>exceeds five</b>.
     */
    public @NonNull Context createWindowContext(@WindowType int type, @Nullable Bundle options)  {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
+1 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ public final class WindowManagerGlobal {
    public static final int ADD_INVALID_DISPLAY = -9;
    public static final int ADD_INVALID_TYPE = -10;
    public static final int ADD_INVALID_USER = -11;
    public static final int ADD_TOO_MANY_TOKENS = -12;

    @UnsupportedAppUsage
    private static WindowManagerGlobal sDefaultWindowManager;
+30 −0
Original line number Diff line number Diff line
@@ -5534,4 +5534,34 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
            }
        }
    }

    /**
     * Returns the number of window tokens without surface on this display. A {@link WindowToken}
     * won't have its {@link SurfaceControl} until a window is added to a {@link WindowToken}.
     * The purpose of this method is to accumulate non-window containing {@link WindowToken}s and
     * limit the usage if the count exceeds a number.
     *
     * @param callingUid app calling uid
     * @return the number of window tokens without surface on this display
     * @see WindowToken#addWindow(WindowState)
     */
    int getWindowTokensWithoutSurfaceCount(int callingUid) {
        List<WindowToken> tokens = new ArrayList<>(mTokenMap.values());
        int count = 0;
        for (int i = tokens.size() - 1; i >= 0; i--) {
            final WindowToken token = tokens.get(i);
            if (callingUid != token.getOwnerUid()) {
                continue;
            }
            // Skip if token is an Activity
            if (token.asActivityRecord() != null) {
                continue;
            }
            if (token.mSurfaceControl != null) {
                continue;
            }
            count++;
        }
        return count;
    }
}
+28 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
import static android.Manifest.permission.STATUS_BAR_SERVICE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
@@ -74,6 +75,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;
import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_BLAST_SYNC;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
@@ -413,6 +415,12 @@ public class WindowManagerService extends IWindowManager.Stub

    private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;

    /** The maximum count of window tokens without surface that an app can register. */
    private static final int MAXIMUM_WINDOW_TOKEN_COUNT_WITHOUT_SURFACE = 5;

    /** System UI can create more window context... */
    private static final int SYSTEM_UI_MULTIPLIER = 2;

    // TODO(b/143053092): Remove the settings if it becomes stable.
    private static final String FIXED_ROTATION_TRANSFORM_SETTING_NAME = "fixed_rotation_transform";
    boolean mIsFixedRotationTransformEnabled;
@@ -2594,10 +2602,30 @@ public class WindowManagerService extends IWindowManager.Stub
    @Override
    public int addWindowTokenWithOptions(IBinder binder, int type, int displayId, Bundle options,
            String packageName) {
        if (tokenCountExceed()) {
            return ADD_TOO_MANY_TOKENS;
        }
        return addWindowTokenWithOptions(binder, type, displayId, options, packageName,
                true /* fromClientToken */);
    }

    private boolean tokenCountExceed() {
        final int callingUid = Binder.getCallingUid();
        // Don't check if caller is from system server.
        if (callingUid == myPid()) {
            return false;
        }
        final int limit =
                (checkCallingPermission(STATUS_BAR_SERVICE, "addWindowTokenWithOptions"))
                        ?  MAXIMUM_WINDOW_TOKEN_COUNT_WITHOUT_SURFACE * SYSTEM_UI_MULTIPLIER
                        : MAXIMUM_WINDOW_TOKEN_COUNT_WITHOUT_SURFACE;
        synchronized (mGlobalLock) {
            int[] count = new int[1];
            mRoot.forAllDisplays(d -> count[0] += d.getWindowTokensWithoutSurfaceCount(callingUid));
            return count[0] >= limit;
        }
    }

    private int addWindowTokenWithOptions(IBinder binder, int type, int displayId, Bundle options,
            String packageName, boolean fromClientToken) {
        final boolean callerCanManageAppTokens =