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

Commit 943002b4 authored by Wale Ogunwale's avatar Wale Ogunwale
Browse files

Set importance for processes displaying app-overlays based on visibility

We were previously setting this based on when the window was added and
removed. This can lead to issues where an app isn't allowed to show
alert windows so window manager hides the window after the permission is
revoked, but the window still exist in the system so the process
importance will still be high. We now set the process importance based
on if it has visible window surfaces or not.

Bug: 33256752
Test: cts/.../run-test CtsAppTestCases android.app.cts.AlertWindowsTests
Change-Id: I4e406a94683ec0eecc0911d0195e641c693e1c4a
parent 91e5d7fa
Loading
Loading
Loading
Loading
+57 −16
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.server.wm;

import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -54,6 +57,8 @@ import com.android.internal.view.IInputMethodManager;
import com.android.server.wm.WindowManagerService.H;

import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;

/**
 * This class represents an active client session.  There is generally one
@@ -70,7 +75,11 @@ public class Session extends IWindowSession.Stub
    private final String mStringName;
    SurfaceSession mSurfaceSession;
    private int mNumWindow = 0;
    private int mNumOverlayWindow = 0;
    // Set of visible application overlay window surfaces connected to this session.
    private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>();
    // Set of visible alert window surfaces connected to this session.
    private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
    final boolean mCanAddInternalSystemWindow;
    private boolean mClientDead = false;
    private float mLastReportedAnimatorScale;

@@ -82,6 +91,8 @@ public class Session extends IWindowSession.Stub
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
        mCanAddInternalSystemWindow = service.mContext.checkCallingPermission(
                INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
        StringBuilder sb = new StringBuilder();
        sb.append("Session{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
@@ -544,7 +555,7 @@ public class Session extends IWindowSession.Stub
        }
    }

    void windowAddedLocked(int type) {
    void windowAddedLocked() {
        if (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
                TAG_WM, "First window added to " + this + ", creating SurfaceSession");
@@ -557,24 +568,52 @@ public class Session extends IWindowSession.Stub
            }
        }
        mNumWindow++;
        if (type == TYPE_APPLICATION_OVERLAY) {
            mNumOverlayWindow++;
            setHasOverlayUi(true);
        }
    }

    void windowRemovedLocked(int type) {
    void windowRemovedLocked() {
        mNumWindow--;
        if (type == TYPE_APPLICATION_OVERLAY) {
            mNumOverlayWindow--;
            if (mNumOverlayWindow == 0) {
                setHasOverlayUi(false);
            } else if (mNumOverlayWindow < 0) {
                throw new IllegalStateException("mNumOverlayWindow=" + mNumOverlayWindow
                        + " less than 0 for session=" + this);
        killSessionLocked();
    }


    void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
            boolean visible, int type) {

        if (!isSystemAlertWindowType(type)) {
            return;
        }

        boolean changed;

        if (!mCanAddInternalSystemWindow) {
            // We want to track non-system signature apps adding alert windows so we can post an
            // on-going notification for the user to control their visibility.
            if (visible) {
                changed = mAlertWindowSurfaces.add(surfaceController);
            } else {
                changed = mAlertWindowSurfaces.remove(surfaceController);
            }

            if (changed) {
                // TODO: Update notification.
            }
        }

        if (type != TYPE_APPLICATION_OVERLAY) {
            return;
        }

        if (visible) {
            changed = mAppOverlaySurfaces.add(surfaceController);
        } else {
            changed = mAppOverlaySurfaces.remove(surfaceController);
        }

        if (changed) {
            // Notify activity manager of changes to app overlay windows so it can adjust the
            // importance score for the process.
            setHasOverlayUi(!mAppOverlaySurfaces.isEmpty());
        }
        killSessionLocked();
    }

    private void killSessionLocked() {
@@ -598,6 +637,7 @@ public class Session extends IWindowSession.Stub
        }
        mSurfaceSession = null;
        setHasOverlayUi(false);
        // TODO: Update notification
    }

    private void setHasOverlayUi(boolean hasOverlayUi) {
@@ -606,7 +646,8 @@ public class Session extends IWindowSession.Stub

    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
                pw.print(" mNumOverlayWindow="); pw.print(mNumOverlayWindow);
                pw.print(" mAppOverlaySurfaces="); pw.print(mAppOverlaySurfaces);
                pw.print(" mAlertWindowSurfaces="); pw.print(mAlertWindowSurfaces);
                pw.print(" mClientDead="); pw.print(mClientDead);
                pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
    }
+3 −5
Original line number Diff line number Diff line
@@ -1111,8 +1111,6 @@ public class WindowManagerService extends IWindowManager.Stub
        long origId;
        final int callingUid = Binder.getCallingUid();
        final int type = attrs.type;
        final boolean ownerCanAddInternalSystemWindow =
                mContext.checkCallingPermission(INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;

        synchronized(mWindowMap) {
            if (!mDisplayReady) {
@@ -1215,7 +1213,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    }
                }
                token = new WindowToken(this, attrs.token, type, false, displayContent,
                        ownerCanAddInternalSystemWindow);
                        session.mCanAddInternalSystemWindow);
            } else if (rootType >= FIRST_APPLICATION_WINDOW && rootType <= LAST_APPLICATION_WINDOW) {
                atoken = token.asAppWindowToken();
                if (atoken == null) {
@@ -1286,12 +1284,12 @@ public class WindowManagerService extends IWindowManager.Stub
                // instead make a new token for it (as if null had been passed in for the token).
                attrs.token = null;
                token = new WindowToken(this, null, type, false, displayContent,
                        ownerCanAddInternalSystemWindow);
                        session.mCanAddInternalSystemWindow);
            }

            final WindowState win = new WindowState(this, session, client, token, parentWindow,
                    appOp[0], seq, attrs, viewVisibility, session.mUid,
                    ownerCanAddInternalSystemWindow);
                    session.mCanAddInternalSystemWindow);
            if (win.mDeathRecipient == null) {
                // Client has apparently died, so there is no reason to
                // continue.
+2 −2
Original line number Diff line number Diff line
@@ -665,7 +665,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

    void attach() {
        if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
        mSession.windowAddedLocked(mAttrs.type);
        mSession.windowAddedLocked();
    }

    @Override
@@ -1738,7 +1738,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP

        mWinAnimator.destroyDeferredSurfaceLocked();
        mWinAnimator.destroySurfaceLocked();
        mSession.windowRemovedLocked(mAttrs.type);
        mSession.windowRemovedLocked();
        try {
            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
        } catch (RuntimeException e) {
+28 −20
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ class WindowSurfaceController {

    private SurfaceControl mSurfaceControl;

    // Should only be set from within setShown().
    private boolean mSurfaceShown = false;
    private float mSurfaceX = 0;
    private float mSurfaceY = 0;
@@ -79,6 +80,9 @@ class WindowSurfaceController {

    private final WindowManagerService mService;

    private final int mWindowType;
    private final Session mWindowSession;

    public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
            int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
        mAnimator = animator;
@@ -89,16 +93,16 @@ class WindowSurfaceController {
        title = name;

        mService = animator.mService;
        final WindowState win = animator.mWin;
        mWindowType = windowType;
        mWindowSession = win.mSession;

        // For opaque child windows placed under parent windows,
        // we use a special SurfaceControl which mirrors commands
        // to a black-out layer placed one Z-layer below the surface.
        // For opaque child windows placed under parent windows, we use a special SurfaceControl
        // which mirrors commands to a black-out layer placed one Z-layer below the surface.
        // This prevents holes to whatever app/wallpaper is underneath.
        if (animator.mWin.isChildWindow() &&
                animator.mWin.mSubLayer < 0 &&
                animator.mWin.mAppToken != null) {
            mSurfaceControl = new SurfaceControlWithBackground(s,
                    name, w, h, format, flags, animator.mWin.mAppToken, windowType, ownerUid);
        if (win.isChildWindow() && win.mSubLayer < 0 && win.mAppToken != null) {
            mSurfaceControl = new SurfaceControlWithBackground(
                    s, name, w, h, format, flags, win.mAppToken, windowType, ownerUid);
        } else if (DEBUG_SURFACE_TRACE) {
            mSurfaceControl = new SurfaceTrace(
                    s, name, w, h, format, flags, windowType, ownerUid);
@@ -109,8 +113,7 @@ class WindowSurfaceController {

        if (mService.mRoot.mSurfaceTraceEnabled) {
            mSurfaceControl = new RemoteSurfaceTrace(
                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(),
                    mSurfaceControl, animator.mWin);
                    mService.mRoot.mSurfaceTraceFd.getFileDescriptor(), mSurfaceControl, win);
        }
    }

@@ -141,15 +144,16 @@ class WindowSurfaceController {
    }

    private void hideSurface() {
        if (mSurfaceControl != null) {
            mSurfaceShown = false;
        if (mSurfaceControl == null) {
            return;
        }
        setShown(false);
        try {
            mSurfaceControl.hide();
        } catch (RuntimeException e) {
            Slog.w(TAG, "Exception hiding surface in " + this);
        }
    }
    }

    void setPositionAndLayer(float left, float top, int layerStack, int layer) {
        mService.openSurfaceTransaction();
@@ -165,7 +169,7 @@ class WindowSurfaceController {

                mSurfaceControl.setLayer(layer);
                mSurfaceControl.setAlpha(0);
                mSurfaceShown = false;
                setShown(false);
            } catch (RuntimeException e) {
                Slog.w(TAG, "Error creating surface in " + this, e);
                mAnimator.reclaimSomeSurfaceMemory("create-init", true);
@@ -188,7 +192,7 @@ class WindowSurfaceController {
        } catch (RuntimeException e) {
            Slog.w(TAG, "Error destroying surface in: " + this, e);
        } finally {
            mSurfaceShown = false;
            setShown(false);
            mSurfaceControl = null;
        }
    }
@@ -447,7 +451,7 @@ class WindowSurfaceController {

    private boolean showSurface() {
        try {
            mSurfaceShown = true;
            setShown(true);
            mSurfaceControl.show();
            return true;
        } catch (RuntimeException e) {
@@ -515,6 +519,10 @@ class WindowSurfaceController {

    void setShown(boolean surfaceShown) {
        mSurfaceShown = surfaceShown;

        if (mWindowSession != null) {
            mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
        }
    }

    float getX() {