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 Original line Diff line number Diff line
@@ -16,7 +16,10 @@


package com.android.server.wm;
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.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_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_POSITIONING;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
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 com.android.server.wm.WindowManagerService.H;


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


/**
/**
 * This class represents an active client session.  There is generally one
 * 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;
    private final String mStringName;
    SurfaceSession mSurfaceSession;
    SurfaceSession mSurfaceSession;
    private int mNumWindow = 0;
    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 boolean mClientDead = false;
    private float mLastReportedAnimatorScale;
    private float mLastReportedAnimatorScale;


@@ -82,6 +91,8 @@ public class Session extends IWindowSession.Stub
        mUid = Binder.getCallingUid();
        mUid = Binder.getCallingUid();
        mPid = Binder.getCallingPid();
        mPid = Binder.getCallingPid();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
        mLastReportedAnimatorScale = service.getCurrentAnimatorScale();
        mCanAddInternalSystemWindow = service.mContext.checkCallingPermission(
                INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
        StringBuilder sb = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        sb.append("Session{");
        sb.append("Session{");
        sb.append(Integer.toHexString(System.identityHashCode(this)));
        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 (mSurfaceSession == null) {
            if (WindowManagerService.localLOGV) Slog.v(
            if (WindowManagerService.localLOGV) Slog.v(
                TAG_WM, "First window added to " + this + ", creating SurfaceSession");
                TAG_WM, "First window added to " + this + ", creating SurfaceSession");
@@ -557,24 +568,52 @@ public class Session extends IWindowSession.Stub
            }
            }
        }
        }
        mNumWindow++;
        mNumWindow++;
        if (type == TYPE_APPLICATION_OVERLAY) {
            mNumOverlayWindow++;
            setHasOverlayUi(true);
        }
    }
    }


    void windowRemovedLocked(int type) {
    void windowRemovedLocked() {
        mNumWindow--;
        mNumWindow--;
        if (type == TYPE_APPLICATION_OVERLAY) {
        killSessionLocked();
            mNumOverlayWindow--;
    }
            if (mNumOverlayWindow == 0) {

                setHasOverlayUi(false);

            } else if (mNumOverlayWindow < 0) {
    void onWindowSurfaceVisibilityChanged(WindowSurfaceController surfaceController,
                throw new IllegalStateException("mNumOverlayWindow=" + mNumOverlayWindow
            boolean visible, int type) {
                        + " less than 0 for session=" + this);

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


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


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


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


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


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


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


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


    private SurfaceControl mSurfaceControl;
    private SurfaceControl mSurfaceControl;


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


    private final WindowManagerService mService;
    private final WindowManagerService mService;


    private final int mWindowType;
    private final Session mWindowSession;

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


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


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


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


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


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


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


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


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


    void setShown(boolean surfaceShown) {
    void setShown(boolean surfaceShown) {
        mSurfaceShown = surfaceShown;
        mSurfaceShown = surfaceShown;

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


    float getX() {
    float getX() {