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

Commit a606a293 authored by Michal Karpinski's avatar Michal Karpinski
Browse files

Don't count toasts as visible windows

in WMS#isAnyWindowVisibleForUid() (now in RootWindowContainer)

Apps could post a toast (or many in a row for that matter) to
trivially bypass the isUidForeground() check.

Bug: 110956953
Test: atest WmTests:ActivityStarterTests
      atest WmTests:RootWindowContainerTests
Test: manual
Change-Id: Ice6571264c35fbf7d4446a5f67a4c44c84d0f9f0
parent efad1da2
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -945,7 +945,7 @@ class ActivityStarter {
    /** Returns true if uid has a visible window or its process is in a top state. */
    private boolean isUidForeground(int uid) {
        return (mService.getUidStateLocked(uid) == ActivityManager.PROCESS_STATE_TOP)
            || mService.mWindowManager.isAnyWindowVisibleForUid(uid);
            || mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid);
    }

    /** Returns true if uid is in a persistent state. */
@@ -968,18 +968,19 @@ class ActivityStarter {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "logActivityStart");
            final int callingUidProcState = mService.getUidStateLocked(callingUid);
            final boolean callingUidHasAnyVisibleWindow =
                    mService.mWindowManager.isAnyWindowVisibleForUid(callingUid);
                    mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(callingUid);
            final int realCallingUidProcState = (callingUid == realCallingUid)
                    ? callingUidProcState
                    : mService.getUidStateLocked(realCallingUid);
            final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
                    ? callingUidHasAnyVisibleWindow
                    : mService.mWindowManager.isAnyWindowVisibleForUid(realCallingUid);
                    : mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(
                            realCallingUid);
            final String targetPackage = (r != null) ? r.packageName : null;
            final int targetUid = (r!= null) ? ((r.appInfo != null) ? r.appInfo.uid : -1) : -1;
            final int targetUidProcState = mService.getUidStateLocked(targetUid);
            final boolean targetUidHasAnyVisibleWindow = (targetUid != -1)
                    ? mService.mWindowManager.isAnyWindowVisibleForUid(targetUid)
                    ? mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(targetUid)
                    : false;
            final String targetWhitelistTag = (targetUid != -1)
                    ? mService.getPendingTempWhitelistTagForUidLocked(targetUid)
+10 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;

import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
@@ -279,6 +280,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        }, true /* traverseTopToBottom */);
    }

    /**
     * Returns true if the callingUid has any non-toast window currently visible to the user.
     */
    boolean isAnyNonToastWindowVisibleForUid(int callingUid) {
        return forAllWindows(w -> {
            return w.getOwningUid() == callingUid && w.isVisible() && w.mAttrs.type != TYPE_TOAST;
        }, true /* traverseTopToBottom */);
    }

    /**
     * Returns the app window token for the input binder if it exist in the system.
     * NOTE: Only one AppWindowToken is allowed to exist in the system for a binder token, since
+0 −11
Original line number Diff line number Diff line
@@ -5715,17 +5715,6 @@ public class WindowManagerService extends IWindowManager.Stub
        }
    }

    /**
     * Returns true if the callingUid has any window currently visible to the user.
     */
    public boolean isAnyWindowVisibleForUid(int callingUid) {
        synchronized (mGlobalLock) {
            return mRoot.forAllWindows(w -> {
                return w.getOwningUid() == callingUid && w.isVisible();
            }, true /* traverseTopToBottom */);
        }
    }

    /**
     * Called when a task has been removed from the recent tasks list.
     * <p>
+4 −4
Original line number Diff line number Diff line
@@ -643,10 +643,10 @@ public class ActivityStarterTests extends ActivityTestsBase {
            boolean hasForegroundActivities, boolean callerIsRecents,
            boolean callerIsTempWhitelisted) {
        // window visibility
        doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager).isAnyWindowVisibleForUid(
                callingUid);
        doReturn(realCallingUidHasVisibleWindow).when(mService.mWindowManager)
                .isAnyWindowVisibleForUid(realCallingUid);
        doReturn(callingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                .isAnyNonToastWindowVisibleForUid(callingUid);
        doReturn(realCallingUidHasVisibleWindow).when(mService.mWindowManager.mRoot)
                .isAnyNonToastWindowVisibleForUid(realCallingUid);
        // process importance
        doReturn(callingUidProcState).when(mService).getUidStateLocked(callingUid);
        doReturn(realCallingUidProcState).when(mService).getUidStateLocked(realCallingUid);
+75 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.platform.test.annotations.Presubmit;

import androidx.test.filters.SmallTest;

import org.junit.Test;

/**
 * Tests for RootWindowContainer.
 *
 * Build/Install/Run:
 *  atest WmTests:RootWindowContainerTests
 */
@SmallTest
@Presubmit
public class RootWindowContainerTests extends WindowTestsBase {

    private static final int FAKE_CALLING_UID = 667;

    @Test
    public void testIsAnyNonToastWindowVisibleForUid_oneToastOneNonToastBothVisible() {
        final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);
        toastyToast.mHasSurface = true;
        app.mHasSurface = true;

        assertTrue(toastyToast.isVisible());
        assertTrue(app.isVisible());
        assertTrue(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
    }

    @Test
    public void testIsAnyNonToastWindowVisibleForUid_onlyToastVisible() {
        final WindowState toastyToast = createWindow(null, TYPE_TOAST, "toast", FAKE_CALLING_UID);
        toastyToast.mHasSurface = true;

        assertTrue(toastyToast.isVisible());
        assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
    }

    @Test
    public void testIsAnyNonToastWindowVisibleForUid_aFewNonToastButNoneVisible() {
        final WindowState topBar = createWindow(null, TYPE_STATUS_BAR, "topBar", FAKE_CALLING_UID);
        final WindowState app = createWindow(null, TYPE_APPLICATION, "app", FAKE_CALLING_UID);

        assertFalse(topBar.isVisible());
        assertFalse(app.isVisible());
        assertFalse(mWm.mRoot.isAnyNonToastWindowVisibleForUid(FAKE_CALLING_UID));
    }
}
Loading