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
This commit is contained in:
Michal Karpinski
2019-01-12 17:29:52 +00:00
parent efad1da2f1
commit a606a2937b
6 changed files with 120 additions and 20 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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>

View File

@@ -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);

View File

@@ -0,0 +1,75 @@
/*
* 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));
}
}

View File

@@ -257,6 +257,14 @@ class WindowTestsBase {
}
}
WindowState createWindow(WindowState parent, int type, String name, int ownerId) {
synchronized (mWm.mGlobalLock) {
return (parent == null)
? createWindow(parent, type, mDisplayContent, name, ownerId)
: createWindow(parent, type, parent.mToken, name, ownerId);
}
}
WindowState createWindowOnStack(WindowState parent, int windowingMode, int activityType,
int type, DisplayContent dc, String name) {
synchronized (mWm.mGlobalLock) {
@@ -277,7 +285,16 @@ class WindowTestsBase {
synchronized (mWm.mGlobalLock) {
final WindowToken token = createWindowToken(
dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
return createWindow(parent, type, token, name);
return createWindow(parent, type, token, name, 0 /* ownerId */);
}
}
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
int ownerId) {
synchronized (mWm.mGlobalLock) {
final WindowToken token = createWindowToken(
dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
return createWindow(parent, type, token, name, ownerId);
}
}
@@ -298,6 +315,14 @@ class WindowTestsBase {
}
}
WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
int ownerId) {
synchronized (mWm.mGlobalLock) {
return createWindow(parent, type, token, name, ownerId,
false /* ownerCanAddInternalSystemWindow */);
}
}
WindowState createWindow(WindowState parent, int type, WindowToken token, String name,
int ownerId, boolean ownerCanAddInternalSystemWindow) {
return createWindow(parent, type, token, name, ownerId, ownerCanAddInternalSystemWindow,