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

Commit f9c91987 authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Update areChannelsBypassingDnd from PreferencesHelper correctly" into main

parents cdb99b76 67706813
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -1986,6 +1986,7 @@ public class PreferencesHelper implements RankingConfig {
     * bypassing DND. It should be called whenever a channel is created, updated, or deleted, or
     * when the current user (or its profiles) change.
     */
    // TODO: b/368247671 - remove fromSystemOrSystemUi argument when modes_ui is inlined.
    private void updateCurrentUserHasChannelsBypassingDnd(int callingUid,
            boolean fromSystemOrSystemUi) {
        ArraySet<Pair<String, Integer>> candidatePkgs = new ArraySet<>();
@@ -2016,7 +2017,12 @@ public class PreferencesHelper implements RankingConfig {
        boolean haveBypassingApps = candidatePkgs.size() > 0;
        if (mCurrentUserHasChannelsBypassingDnd != haveBypassingApps) {
            mCurrentUserHasChannelsBypassingDnd = haveBypassingApps;
            updateZenPolicy(mCurrentUserHasChannelsBypassingDnd, callingUid, fromSystemOrSystemUi);
            if (android.app.Flags.modesUi()) {
                mZenModeHelper.updateHasPriorityChannels(mCurrentUserHasChannelsBypassingDnd);
            } else {
                updateZenPolicy(mCurrentUserHasChannelsBypassingDnd, callingUid,
                        fromSystemOrSystemUi);
            }
        }
    }

@@ -2034,6 +2040,9 @@ public class PreferencesHelper implements RankingConfig {
        return true;
    }

    // TODO: b/368247671 - delete this method when modes_ui is inlined, as
    //                     updateCurrentUserHasChannelsBypassingDnd was the only caller and
    //                     PreferencesHelper should otherwise not need to modify actual policy
    public void updateZenPolicy(boolean areChannelsBypassingDnd, int callingUid,
            boolean fromSystemOrSystemUi) {
        NotificationManager.Policy policy = mZenModeHelper.getNotificationPolicy();
+22 −0
Original line number Diff line number Diff line
@@ -1567,6 +1567,28 @@ public class ZenModeHelper {
        return azr;
    }

    // Update only the hasPriorityChannels state (aka areChannelsBypassingDnd) without modifying
    // any of the rest of the existing policy. This allows components that only want to modify
    // this bit (PreferencesHelper) to not have to adjust the rest of the policy.
    protected void updateHasPriorityChannels(boolean hasPriorityChannels) {
        if (!Flags.modesUi()) {
            Log.wtf(TAG, "updateHasPriorityChannels called without modes_ui");
        }
        synchronized (mConfigLock) {
            // If it already matches, do nothing
            if (mConfig.areChannelsBypassingDnd == hasPriorityChannels) {
                return;
            }

            ZenModeConfig newConfig = mConfig.copy();
            newConfig.areChannelsBypassingDnd = hasPriorityChannels;
            // The updated calculation of whether there are priority channels is always done by
            // the system, even if the event causing the calculation had a different origin.
            setConfigLocked(newConfig, null, ORIGIN_SYSTEM, "updateHasPriorityChannels",
                    Process.SYSTEM_UID);
        }
    }

    @SuppressLint("MissingPermission")
    void scheduleActivationBroadcast(String pkg, @UserIdInt int userId, String ruleId,
            boolean activated) {
+93 −19
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.notification;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.Flags.FLAG_MODES_UI;
import static android.app.Notification.VISIBILITY_PRIVATE;
import static android.app.Notification.VISIBILITY_SECRET;
import static android.app.NotificationChannel.ALLOW_BUBBLE_ON;
@@ -81,6 +82,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -248,7 +250,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
    @Parameters(name = "{0}")
    public static List<FlagsParameterization> getParams() {
        return FlagsParameterization.allCombinationsOf(
                FLAG_NOTIFICATION_CLASSIFICATION);
                FLAG_NOTIFICATION_CLASSIFICATION, FLAG_MODES_UI);
    }

    public PreferencesHelperTest(FlagsParameterization flags) {
@@ -2701,7 +2703,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // create notification channel that can bypass dnd
@@ -2711,18 +2717,30 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                uid, false);
        assertTrue(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(true));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // delete channels
        mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId(), uid, false);
        assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId(), uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2738,7 +2756,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // Recreate a channel & now the app has dnd access granted and can set the bypass dnd field
@@ -2748,7 +2770,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
                uid, false);

        assertTrue(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(true));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2764,7 +2790,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // create notification channel that can bypass dnd, using local app level settings
@@ -2774,18 +2804,30 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                uid, false);
        assertTrue(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(true));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // delete channels
        mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId(), uid, false);
        assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId(), uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2812,7 +2854,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2834,7 +2880,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2856,7 +2906,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2872,7 +2926,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false,
                uid, false);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // update channel so it CAN bypass dnd:
@@ -2880,7 +2938,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        channel.setBypassDnd(true);
        mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true, SYSTEM_UID, true);
        assertTrue(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(true));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();

        // update channel so it can't bypass dnd:
@@ -2888,7 +2950,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        channel.setBypassDnd(false);
        mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true, SYSTEM_UID, true);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2901,7 +2967,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
        mHelper.syncChannelsBypassingDnd();
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, times(1)).updateHasPriorityChannels(eq(false));
        } else {
            verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

@@ -2911,7 +2981,11 @@ public class PreferencesHelperTest extends UiServiceTestCase {
        mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0);
        when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
        assertFalse(mHelper.areChannelsBypassingDnd());
        if (android.app.Flags.modesUi()) {
            verify(mMockZenModeHelper, never()).updateHasPriorityChannels(anyBoolean());
        } else {
            verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyInt());
        }
        resetZenModeHelper();
    }

+23 −0
Original line number Diff line number Diff line
@@ -7027,6 +7027,29 @@ public class ZenModeHelperTest extends UiServiceTestCase {
                ZenModeConfig.EVENTS_OBSOLETE_RULE_ID);
    }

    @Test
    @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI})
    public void updateHasPriorityChannels_keepsChannelSettings() {
        setupZenConfig();

        // Set priority channels setting on manual mode to confirm that it is unaffected by changes
        // to the state describing the existence of such channels.
        mZenModeHelper.mConfig.manualRule.zenPolicy =
                new ZenPolicy.Builder(mZenModeHelper.mConfig.manualRule.zenPolicy)
                        .allowPriorityChannels(false)
                        .build();

        mZenModeHelper.updateHasPriorityChannels(true);
        assertThat(mZenModeHelper.getNotificationPolicy().hasPriorityChannels()).isTrue();

        // getNotificationPolicy() gets its policy from the manual rule; channels not permitted
        assertThat(mZenModeHelper.getNotificationPolicy().allowPriorityChannels()).isFalse();

        mZenModeHelper.updateHasPriorityChannels(false);
        assertThat(mZenModeHelper.getNotificationPolicy().hasPriorityChannels()).isFalse();
        assertThat(mZenModeHelper.getNotificationPolicy().allowPriorityChannels()).isFalse();
    }

    private static void addZenRule(ZenModeConfig config, String id, String ownerPkg, int zenMode,
            @Nullable ZenPolicy zenPolicy) {
        ZenRule rule = new ZenRule();