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

Commit 51e2a10f authored by Bernardo Rufino's avatar Bernardo Rufino Committed by Automerger Merge Worker
Browse files

Merge "Allow custom toasts only if app has resumed activity" into rvc-dev am:...

Merge "Allow custom toasts only if app has resumed activity" into rvc-dev am: 9bcbce4a am: 03cf95f5 am: ec6017f3 am: 73dfb022

Change-Id: I0c64ba2bcd9d6da7c4d58fef045253ef8271e336
parents cca1024c 73dfb022
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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(),
@@ -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;
@@ -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(),
@@ -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 {
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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.
     *
+14 −0
Original line number Diff line number Diff line
@@ -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) {
+10 −0
Original line number Diff line number Diff line
@@ -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()) {
+16 −14
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -253,6 +253,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
    @Mock
    IActivityManager mAm;
    @Mock
    ActivityTaskManagerInternal mAtm;
    @Mock
    IUriGrantsManager mUgm;
    @Mock
    UriGrantsManagerInternal mUgmInternal;
@@ -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);
@@ -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(),
@@ -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(),
@@ -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(),
@@ -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(),
@@ -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(),
@@ -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(),
@@ -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