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

Commit 0c402393 authored by Jernej Virag's avatar Jernej Virag Committed by Android (Google) Code Review
Browse files

Merge "Cleanup register_zen_mode_content_observer_background flag" into main

parents 178fbe87 14877a97
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -812,16 +812,6 @@ flag {
    }
}

flag {
    name: "register_zen_mode_content_observer_background"
    namespace: "systemui"
    description: "Decide whether to register zen mode content observers in the background thread."
    bug: "324515627"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "clipboard_noninteractive_on_lockscreen"
    namespace: "systemui"
+207 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.systemui.statusbar.policy

import android.app.NotificationManager
import android.os.Handler
import android.provider.Settings
import android.service.notification.ZenModeConfig
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.testScope
import com.android.systemui.settings.userTracker
import com.android.systemui.testKosmos
import com.android.systemui.util.settings.fakeGlobalSettings
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mockito
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
class ZenModeControllerImplTest : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private lateinit var testableLooper: TestableLooper
    private lateinit var controller: ZenModeControllerImpl

    private val globalSettings = kosmos.fakeGlobalSettings
    private val config: ZenModeConfig = mock<ZenModeConfig>()
    private val mNm: NotificationManager = mock<NotificationManager>()

    @Before
    fun setUp() {
        testableLooper = TestableLooper.get(this)
        mContext.addMockSystemService(NotificationManager::class.java, mNm)
        whenever(mNm.zenModeConfig).thenReturn(config)

        controller =
            ZenModeControllerImpl(
                mContext,
                Handler.createAsync(testableLooper.looper),
                kosmos.broadcastDispatcher,
                kosmos.dumpManager,
                globalSettings,
                kosmos.userTracker,
            )
    }

    @Test
    fun testRemoveDuringCallback() {
        val callback =
            object : ZenModeController.Callback {
                override fun onConfigChanged(config: ZenModeConfig) {
                    controller.removeCallback(this)
                }
            }

        controller.addCallback(callback)
        val mockCallback = Mockito.mock(ZenModeController.Callback::class.java)
        controller.addCallback(mockCallback)
        controller.fireConfigChanged(config)
        Mockito.verify(mockCallback).onConfigChanged(ArgumentMatchers.eq(config))
    }

    @Test
    fun testAreNotificationsHiddenInShade_zenOffShadeSuppressed() {
        config.suppressedVisualEffects =
            NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
        controller.updateZenMode(Settings.Global.ZEN_MODE_OFF)
        controller.updateZenModeConfig()
        assertThat(controller.areNotificationsHiddenInShade()).isFalse()
    }

    @Test
    fun testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() {
        val policy =
            NotificationManager.Policy(
                0,
                0,
                0,
                NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR,
            )
        whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy)
        controller.updateConsolidatedNotificationPolicy()
        controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
        assertThat(controller.areNotificationsHiddenInShade()).isFalse()
    }

    @Test
    fun testAreNotificationsHiddenInShade_zenOnShadeSuppressed() {
        val policy =
            NotificationManager.Policy(
                0,
                0,
                0,
                NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST,
            )
        whenever(mNm.consolidatedNotificationPolicy).thenReturn(policy)
        controller.updateConsolidatedNotificationPolicy()
        controller.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
        assertThat(controller.areNotificationsHiddenInShade()).isTrue()
    }

    @Test
    fun testModeChange() =
        testScope.runTest {
            val states =
                listOf(
                    Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                    Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                    Settings.Global.ZEN_MODE_ALARMS,
                    Settings.Global.ZEN_MODE_ALARMS,
                )

            for (state in states) {
                globalSettings.putInt(Settings.Global.ZEN_MODE, state)
                testScope.runCurrent()
                testableLooper.processAllMessages()
                assertThat(controller.zen).isEqualTo(state)
            }
        }

    @Test
    fun testModeChange_callbackNotified() =
        testScope.runTest {
            val currentState = AtomicInteger(-1)

            val callback: ZenModeController.Callback =
                object : ZenModeController.Callback {
                    override fun onZenChanged(zen: Int) {
                        currentState.set(zen)
                    }
                }

            controller.addCallback(callback)

            val states =
                listOf(
                    Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                    Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                    Settings.Global.ZEN_MODE_ALARMS,
                    Settings.Global.ZEN_MODE_ALARMS,
                )

            for (state in states) {
                globalSettings.putInt(Settings.Global.ZEN_MODE, state)
                testScope.runCurrent()
                testableLooper.processAllMessages()
                assertThat(currentState.get()).isEqualTo(state)
            }
        }

    @Test
    fun testCallbackRemovedWhileDispatching_doesntCrash() =
        testScope.runTest {
            val remove = AtomicBoolean(false)
            globalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF)
            testableLooper.processAllMessages()
            val callback: ZenModeController.Callback =
                object : ZenModeController.Callback {
                    override fun onZenChanged(zen: Int) {
                        if (remove.get()) {
                            controller.removeCallback(this)
                        }
                    }
                }
            controller.addCallback(callback)
            controller.addCallback(object : ZenModeController.Callback {})

            remove.set(true)

            globalSettings.putInt(
                Settings.Global.ZEN_MODE,
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
            )
            testScope.runCurrent()
            testableLooper.processAllMessages()
        }
}
+3 −15
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.systemui.statusbar.policy;

import static com.android.systemui.Flags.registerZenModeContentObserverBackground;

import android.app.AlarmManager;
import android.app.Flags;
import android.app.NotificationManager;
@@ -47,7 +45,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.settings.UserTracker;
@@ -107,7 +104,6 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
    public ZenModeControllerImpl(
            Context context,
            @Main Handler handler,
            @Background Handler bgHandler,
            BroadcastDispatcher broadcastDispatcher,
            DumpManager dumpManager,
            GlobalSettings globalSettings,
@@ -138,17 +134,9 @@ public class ZenModeControllerImpl implements ZenModeController, Dumpable {
            }
        };
        mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        if (registerZenModeContentObserverBackground()) {
            bgHandler.post(() -> {
                globalSettings.registerContentObserverSync(Global.ZEN_MODE, modeContentObserver);
                globalSettings.registerContentObserverSync(Global.ZEN_MODE_CONFIG_ETAG,
                        configContentObserver);
            });
        } else {
            globalSettings.registerContentObserverSync(Global.ZEN_MODE, modeContentObserver);
            globalSettings.registerContentObserverSync(Global.ZEN_MODE_CONFIG_ETAG,
        globalSettings.registerContentObserverAsync(Global.ZEN_MODE, modeContentObserver);
        globalSettings.registerContentObserverAsync(Global.ZEN_MODE_CONFIG_ETAG,
                configContentObserver);
        }
        updateZenMode(getModeSettingValueFromProvider());
        updateZenModeConfig();
        updateConsolidatedNotificationPolicy();
+0 −201
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.systemui.statusbar.policy;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.NotificationManager;
import android.os.Handler;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.ZenModeController.Callback;
import com.android.systemui.util.settings.FakeGlobalSettings;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper
public class ZenModeControllerImplTest extends SysuiTestCase {

    private Callback mCallback;
    @Mock
    NotificationManager mNm;
    @Mock
    ZenModeConfig mConfig;
    @Mock
    BroadcastDispatcher mBroadcastDispatcher;
    @Mock
    DumpManager mDumpManager;
    @Mock
    UserTracker mUserTracker;
    private ZenModeControllerImpl mController;

    private final FakeGlobalSettings mGlobalSettings = new FakeGlobalSettings();

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mContext.addMockSystemService(NotificationManager.class, mNm);
        when(mNm.getZenModeConfig()).thenReturn(mConfig);

        mController = new ZenModeControllerImpl(
                mContext,
                Handler.createAsync(TestableLooper.get(this).getLooper()),
                Handler.createAsync(TestableLooper.get(this).getLooper()),
                mBroadcastDispatcher,
                mDumpManager,
                mGlobalSettings,
                mUserTracker);
    }

    @Test
    public void testRemoveDuringCallback() {
        mCallback = new Callback() {
            @Override
            public void onConfigChanged(ZenModeConfig config) {
                mController.removeCallback(mCallback);
            }
        };
        mController.addCallback(mCallback);
        Callback mockCallback = mock(Callback.class);
        mController.addCallback(mockCallback);
        mController.fireConfigChanged(null);
        verify(mockCallback).onConfigChanged(eq(null));
    }

    @Test
    public void testAreNotificationsHiddenInShade_zenOffShadeSuppressed() {
        mConfig.suppressedVisualEffects =
                NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
        mController.updateZenMode(Settings.Global.ZEN_MODE_OFF);
        mController.updateZenModeConfig();

        assertFalse(mController.areNotificationsHiddenInShade());
    }

    @Test
    public void testAreNotificationsHiddenInShade_zenOnShadeNotSuppressed() {
        NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0,
                NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR);
        when(mNm.getConsolidatedNotificationPolicy()).thenReturn(policy);
        mController.updateConsolidatedNotificationPolicy();
        mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);

        assertFalse(mController.areNotificationsHiddenInShade());
    }

    @Test
    public void testAreNotificationsHiddenInShade_zenOnShadeSuppressed() {
        NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0,
                NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST);
        when(mNm.getConsolidatedNotificationPolicy()).thenReturn(policy);
        mController.updateConsolidatedNotificationPolicy();
        mController.updateZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);

        assertTrue(mController.areNotificationsHiddenInShade());
    }

    @Test
    public void testModeChange() {
        List<Integer> states = List.of(
                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_ALARMS,
                Settings.Global.ZEN_MODE_ALARMS
        );

        for (Integer state : states) {
            mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state);
            TestableLooper.get(this).processAllMessages();
            assertEquals(state.intValue(), mController.getZen());
        }
    }

    @Test
    public void testModeChange_callbackNotified() {
        final AtomicInteger currentState = new AtomicInteger(-1);

        ZenModeController.Callback callback = new Callback() {
            @Override
            public void onZenChanged(int zen) {
                currentState.set(zen);
            }
        };

        mController.addCallback(callback);

        List<Integer> states = List.of(
                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS,
                Settings.Global.ZEN_MODE_ALARMS,
                Settings.Global.ZEN_MODE_ALARMS
        );

        for (Integer state : states) {
            mGlobalSettings.putInt(Settings.Global.ZEN_MODE, state);
            TestableLooper.get(this).processAllMessages();
            assertEquals(state.intValue(), currentState.get());
        }

    }

    @Test
    public void testCallbackRemovedWhileDispatching_doesntCrash() {
        final AtomicBoolean remove = new AtomicBoolean(false);
        mGlobalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
        TestableLooper.get(this).processAllMessages();
        final ZenModeController.Callback callback = new ZenModeController.Callback() {
            @Override
            public void onZenChanged(int zen) {
                if (remove.get()) {
                    mController.removeCallback(this);
                }
            }
        };
        mController.addCallback(callback);
        mController.addCallback(new ZenModeController.Callback() {});

        remove.set(true);

        mGlobalSettings.putInt(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_NO_INTERRUPTIONS);
        TestableLooper.get(this).processAllMessages();
    }
}