Loading services/core/java/com/android/server/notification/NotificationManagerService.java +33 −5 Original line number Diff line number Diff line Loading @@ -264,6 +264,7 @@ import com.android.server.pm.PackageManagerService; import com.android.server.policy.PhoneWindowManager; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; import libcore.io.IoUtils; Loading Loading @@ -394,6 +395,7 @@ public class NotificationManagerService extends SystemService { private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L; private IActivityManager mAm; private ActivityTaskManagerInternal mAtm; private ActivityManager mActivityManager; private IPackageManager mPackageManager; private PackageManager mPackageManagerClient; Loading Loading @@ -1861,10 +1863,10 @@ public class NotificationManagerService extends SystemService { ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper, NotificationUsageStats usageStats, AtomicFile policyFile, ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am, UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm, IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager, NotificationHistoryManager historyManager, StatsManager statsManager) { ActivityTaskManagerInternal atm, UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm, IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager, NotificationHistoryManager historyManager, StatsManager statsManager) { mHandler = handler; Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Loading @@ -1874,6 +1876,7 @@ public class NotificationManagerService extends SystemService { mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mAm = am; mAtm = atm; mUgm = ugm; mUgmInternal = ugmInternal; mPackageManager = packageManager; Loading Loading @@ -2060,6 +2063,7 @@ public class NotificationManagerService extends SystemService { systemDir, "notification_policy.xml"), "notification-policy"), (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE), getGroupHelper(), ActivityManager.getService(), LocalServices.getService(ActivityTaskManagerInternal.class), LocalServices.getService(UsageStatsManagerInternal.class), LocalServices.getService(DevicePolicyManagerInternal.class), UriGrantsManager.getService(), Loading Loading @@ -2796,7 +2800,9 @@ public class NotificationManagerService extends SystemService { return; } if (callback != null && !appIsForeground && !isSystemToast && isCustom) { boolean isAppRenderedToast = (callback != null); if (isAppRenderedToast && isCustom && !isSystemToast && !isPackageInForegroundForToast(pkg, callingUid)) { boolean block; long id = Binder.clearCallingIdentity(); try { Loading Loading @@ -2874,6 +2880,28 @@ public class NotificationManagerService extends SystemService { } } /** * Implementation note: Our definition of foreground for toasts is an implementation matter * and should strike a balance between functionality and anti-abuse effectiveness. We * currently worry about the following cases: * <ol> * <li>App with fullscreen activity: Allow toasts * <li>App behind translucent activity from other app: Block toasts * <li>App in multi-window: Allow toasts * <li>App with expanded bubble: Allow toasts * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts * </ol> * Checking if the UID has any resumed activities satisfy use-cases above. * * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has * any visible activities, failing case 2 in list above. */ private boolean isPackageInForegroundForToast(String pkg, int callingUid) { return mAtm.hasResumedActivity(callingUid); } @Override public void cancelToast(String pkg, IBinder token) { Slog.i(TAG, "cancelToast pkg=" + pkg + " token=" + token); Loading services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,11 @@ public abstract class ActivityTaskManagerInternal { */ public abstract List<IBinder> getTopVisibleActivities(); /** * Returns whether {@code uid} has any resumed activity. */ public abstract boolean hasResumedActivity(int uid); /** * Notify listeners that contents are drawn for the first time on a single task display. * Loading services/core/java/com/android/server/wm/ActivityTaskManagerService.java +14 −0 Original line number Diff line number Diff line Loading @@ -6171,6 +6171,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } @Override public boolean hasResumedActivity(int uid) { synchronized (mGlobalLock) { final ArraySet<WindowProcessController> processes = mProcessMap.getProcesses(uid); for (int i = 0, n = processes.size(); i < n; i++) { final WindowProcessController process = processes.valueAt(i); if (process.hasResumedActivity()) { return true; } } } return false; } @Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) { Loading services/core/java/com/android/server/wm/WindowProcessController.java +10 −0 Original line number Diff line number Diff line Loading @@ -751,6 +751,16 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return false; } boolean hasResumedActivity() { for (int i = mActivities.size() - 1; i >= 0; --i) { final ActivityRecord activity = mActivities.get(i); if (activity.isState(RESUMED)) { return true; } } return false; } void updateIntentForHeavyWeightActivity(Intent intent) { if (mActivities.isEmpty()) { Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +16 −14 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_AUTO_CANCEL; Loading Loading @@ -165,6 +164,7 @@ import com.android.server.notification.NotificationManagerService.NotificationAs import com.android.server.notification.NotificationManagerService.NotificationListeners; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; import org.junit.After; Loading Loading @@ -253,6 +253,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock IActivityManager mAm; @Mock ActivityTaskManagerInternal mAtm; @Mock IUriGrantsManager mUgm; @Mock UriGrantsManagerInternal mUgmInternal; Loading Loading @@ -454,7 +456,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAppUsageStats, mGroupHelper, mAm, mAtm, mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppOpsManager, mUm, mHistoryManager, mStatsManager); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); Loading Loading @@ -4704,8 +4706,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND); setAppInForegroundForToasts(mUid, true); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4723,8 +4724,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_NONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> no toasts enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4742,8 +4742,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND); setAppInForegroundForToasts(mUid, true); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), Loading @@ -4761,8 +4760,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_NONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), Loading Loading @@ -4820,8 +4818,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> no toasts enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4843,8 +4840,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> system toast can still be enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4852,6 +4848,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mService.mToastQueue.size()); } private void setAppInForegroundForToasts(int uid, boolean inForeground) { int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE; when(mActivityManager.getUidImportance(mUid)).thenReturn(importance); when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground); } @Test public void testOnPanelRevealedAndHidden() { int items = 5; Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +33 −5 Original line number Diff line number Diff line Loading @@ -264,6 +264,7 @@ import com.android.server.pm.PackageManagerService; import com.android.server.policy.PhoneWindowManager; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; import libcore.io.IoUtils; Loading Loading @@ -394,6 +395,7 @@ public class NotificationManagerService extends SystemService { private static final long CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK = 128611929L; private IActivityManager mAm; private ActivityTaskManagerInternal mAtm; private ActivityManager mActivityManager; private IPackageManager mPackageManager; private PackageManager mPackageManagerClient; Loading Loading @@ -1861,10 +1863,10 @@ public class NotificationManagerService extends SystemService { ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper, NotificationUsageStats usageStats, AtomicFile policyFile, ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am, UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm, IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager, NotificationHistoryManager historyManager, StatsManager statsManager) { ActivityTaskManagerInternal atm, UsageStatsManagerInternal appUsageStats, DevicePolicyManagerInternal dpm, IUriGrantsManager ugm, UriGrantsManagerInternal ugmInternal, AppOpsManager appOps, UserManager userManager, NotificationHistoryManager historyManager, StatsManager statsManager) { mHandler = handler; Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Loading @@ -1874,6 +1876,7 @@ public class NotificationManagerService extends SystemService { mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mAm = am; mAtm = atm; mUgm = ugm; mUgmInternal = ugmInternal; mPackageManager = packageManager; Loading Loading @@ -2060,6 +2063,7 @@ public class NotificationManagerService extends SystemService { systemDir, "notification_policy.xml"), "notification-policy"), (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE), getGroupHelper(), ActivityManager.getService(), LocalServices.getService(ActivityTaskManagerInternal.class), LocalServices.getService(UsageStatsManagerInternal.class), LocalServices.getService(DevicePolicyManagerInternal.class), UriGrantsManager.getService(), Loading Loading @@ -2796,7 +2800,9 @@ public class NotificationManagerService extends SystemService { return; } if (callback != null && !appIsForeground && !isSystemToast && isCustom) { boolean isAppRenderedToast = (callback != null); if (isAppRenderedToast && isCustom && !isSystemToast && !isPackageInForegroundForToast(pkg, callingUid)) { boolean block; long id = Binder.clearCallingIdentity(); try { Loading Loading @@ -2874,6 +2880,28 @@ public class NotificationManagerService extends SystemService { } } /** * Implementation note: Our definition of foreground for toasts is an implementation matter * and should strike a balance between functionality and anti-abuse effectiveness. We * currently worry about the following cases: * <ol> * <li>App with fullscreen activity: Allow toasts * <li>App behind translucent activity from other app: Block toasts * <li>App in multi-window: Allow toasts * <li>App with expanded bubble: Allow toasts * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts * </ol> * Checking if the UID has any resumed activities satisfy use-cases above. * * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has * any visible activities, failing case 2 in list above. */ private boolean isPackageInForegroundForToast(String pkg, int callingUid) { return mAtm.hasResumedActivity(callingUid); } @Override public void cancelToast(String pkg, IBinder token) { Slog.i(TAG, "cancelToast pkg=" + pkg + " token=" + token); Loading
services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +5 −0 Original line number Diff line number Diff line Loading @@ -168,6 +168,11 @@ public abstract class ActivityTaskManagerInternal { */ public abstract List<IBinder> getTopVisibleActivities(); /** * Returns whether {@code uid} has any resumed activity. */ public abstract boolean hasResumedActivity(int uid); /** * Notify listeners that contents are drawn for the first time on a single task display. * Loading
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +14 −0 Original line number Diff line number Diff line Loading @@ -6171,6 +6171,20 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } @Override public boolean hasResumedActivity(int uid) { synchronized (mGlobalLock) { final ArraySet<WindowProcessController> processes = mProcessMap.getProcesses(uid); for (int i = 0, n = processes.size(); i < n; i++) { final WindowProcessController process = processes.valueAt(i); if (process.hasResumedActivity()) { return true; } } } return false; } @Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) { Loading
services/core/java/com/android/server/wm/WindowProcessController.java +10 −0 Original line number Diff line number Diff line Loading @@ -751,6 +751,16 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return false; } boolean hasResumedActivity() { for (int i = mActivities.size() - 1; i >= 0; --i) { final ActivityRecord activity = mActivities.get(i); if (activity.isState(RESUMED)) { return true; } } return false; } void updateIntentForHeavyWeightActivity(Intent intent) { if (mActivities.isEmpty()) { Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +16 −14 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; import static android.app.Notification.CATEGORY_CALL; import static android.app.Notification.FLAG_AUTO_CANCEL; Loading Loading @@ -165,6 +164,7 @@ import com.android.server.notification.NotificationManagerService.NotificationAs import com.android.server.notification.NotificationManagerService.NotificationListeners; import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; import org.junit.After; Loading Loading @@ -253,6 +253,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock IActivityManager mAm; @Mock ActivityTaskManagerInternal mAtm; @Mock IUriGrantsManager mUgm; @Mock UriGrantsManagerInternal mUgmInternal; Loading Loading @@ -454,7 +456,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAppUsageStats, mGroupHelper, mAm, mAtm, mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, mAppOpsManager, mUm, mHistoryManager, mStatsManager); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); Loading Loading @@ -4704,8 +4706,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND); setAppInForegroundForToasts(mUid, true); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4723,8 +4724,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_NONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> no toasts enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4742,8 +4742,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_FOREGROUND); setAppInForegroundForToasts(mUid, true); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), Loading @@ -4761,8 +4760,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) .thenReturn(false); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_NONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> toast should still enqueue ((INotificationManager) mService.mService).enqueueTextToast(testPackage, new Binder(), Loading Loading @@ -4820,8 +4818,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> no toasts enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4843,8 +4840,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mService.setPreferencesHelper(mPreferencesHelper); when(mPreferencesHelper.getImportance(testPackage, mUid)).thenReturn(IMPORTANCE_NONE); // this app is NOT in the foreground when(mActivityManager.getUidImportance(mUid)).thenReturn(IMPORTANCE_GONE); setAppInForegroundForToasts(mUid, false); // enqueue toast -> system toast can still be enqueued ((INotificationManager) mService.mService).enqueueToast(testPackage, new Binder(), Loading @@ -4852,6 +4848,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { assertEquals(1, mService.mToastQueue.size()); } private void setAppInForegroundForToasts(int uid, boolean inForeground) { int importance = (inForeground) ? IMPORTANCE_FOREGROUND : IMPORTANCE_NONE; when(mActivityManager.getUidImportance(mUid)).thenReturn(importance); when(mAtm.hasResumedActivity(uid)).thenReturn(inForeground); } @Test public void testOnPanelRevealedAndHidden() { int items = 5; Loading