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

Commit 55aff04e authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I1b4fa593,I89d24e41 into main

* changes:
  Remove redundant val from Icon#equals
  [Dual Shade] Show icon and text in EmptyShadeView
parents 2978bcd1 d1af8469
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -59,6 +59,13 @@ flag {
  bug: "375010573"
}

flag {
  name: "show_icon_in_empty_shade"
  namespace: "systemui"
  description: "Show a representative icon when there are no notifications in the shade."
  bug: "388472403"
}

flag {
   name: "notification_row_is_removed_fix"
   namespace: "systemui"
+116 −10
Original line number Diff line number Diff line
@@ -18,13 +18,18 @@ package com.android.systemui.statusbar.notification.emptyshade.ui.viewmodel

import android.app.NotificationManager.Policy
import android.content.res.Configuration
import android.content.testableContext
import android.graphics.drawable.TestStubDrawable
import android.os.LocaleList
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.provider.Settings
import android.service.notification.ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.data.repository.updateNotificationPolicy
import com.android.settingslib.notification.modes.TestModeBuilder
import com.android.settingslib.notification.modes.ZenMode
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.flags.andSceneContainer
@@ -32,12 +37,15 @@ import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.res.R
import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.emptyshade.ui.shared.flag.ShowIconInEmptyShade
import com.android.systemui.statusbar.policy.data.repository.zenModeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import java.util.Locale
import kotlinx.coroutines.flow.map
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -48,7 +56,15 @@ import platform.test.runner.parameterized.Parameters
@RunWith(ParameterizedAndroidJunit4::class)
@SmallTest
class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
    private val kosmos = testKosmos().apply { useUnconfinedTestDispatcher() }
    private val kosmos =
        testKosmos().apply {
            useUnconfinedTestDispatcher()
            testableContext.orCreateTestableResources.apply {
                addOverride(DND_DRAWABLE_ID, TestStubDrawable("dnd"))
                addOverride(BEDTIME_DRAWABLE_ID, TestStubDrawable("bedtime"))
                addOverride(THEATER_DRAWABLE_ID, TestStubDrawable("theater"))
            }
        }
    private val fakeConfigurationRepository = kosmos.fakeConfigurationRepository

    /** Backup of the current locales, to be restored at the end of the test if they are changed. */
@@ -62,6 +78,10 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf().andSceneContainer()
        }

        const val DND_DRAWABLE_ID = com.android.internal.R.drawable.ic_zen_mode_type_special_dnd
        const val BEDTIME_DRAWABLE_ID = com.android.internal.R.drawable.ic_zen_mode_type_driving
        const val THEATER_DRAWABLE_ID = com.android.internal.R.drawable.ic_zen_mode_type_theater
    }

    init {
@@ -123,6 +143,7 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
        }

    @Test
    @DisableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun text_changesWhenLocaleChanges() =
        kosmos.runTest {
            val text by collectLastValue(underTest.text)
@@ -141,21 +162,41 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
        }

    @Test
    @EnableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun messageString_changesWhenLocaleChanges() =
        kosmos.runTest {
            val text by collectLastValue(underTest.message.map { it.message })

            zenModeRepository.updateMode(ZenMode.MANUAL_DND_MODE_ID) {
                TestModeBuilder(it)
                    .setActive(true)
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            }
            assertThat(text).isEqualTo("Notifications paused by Do Not Disturb")

            updateLocales(LocaleList(Locale.GERMAN))
            assertThat(text).isEqualTo("Benachrichtigungen durch Do Not Disturb pausiert")

            // Make sure we restore the original locales
            updateLocales(originalLocales)
        }

    @Test
    @DisableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun text_reflectsModesHidingNotifications() =
        kosmos.runTest {
            val text by collectLastValue(underTest.text)

            assertThat(text).isEqualTo("No notifications")

            zenModeRepository.addMode(
                TestModeBuilder()
                    .setId("Do not disturb")
                    .setName("Do not disturb")
            zenModeRepository.updateMode(ZenMode.MANUAL_DND_MODE_ID) {
                TestModeBuilder(it)
                    .setActive(true)
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            )
            assertThat(text).isEqualTo("Notifications paused by Do not disturb")
            }
            assertThat(text).isEqualTo("Notifications paused by Do Not Disturb")

            zenModeRepository.addMode(
                TestModeBuilder()
@@ -165,7 +206,7 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            )
            assertThat(text).isEqualTo("Notifications paused by Do not disturb and one other mode")
            assertThat(text).isEqualTo("Notifications paused by Do Not Disturb and one other mode")

            zenModeRepository.addMode(
                TestModeBuilder()
@@ -175,14 +216,68 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            )
            assertThat(text).isEqualTo("Notifications paused by Do not disturb and 2 other modes")
            assertThat(text).isEqualTo("Notifications paused by Do Not Disturb and 2 other modes")

            zenModeRepository.deactivateMode("Do not disturb")
            zenModeRepository.deactivateMode(ZenMode.MANUAL_DND_MODE_ID)
            zenModeRepository.deactivateMode("Work")
            assertThat(text).isEqualTo("Notifications paused by Gym")
        }

    @Test
    @EnableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun message_reflectsModesHidingNotifications() =
        kosmos.runTest {
            val message by collectLastValue(underTest.message)

            assertThat(message?.message).isEqualTo("You're all caught up!")
            assertThat(message?.icon?.resId).isEqualTo(R.drawable.ic_trophy)

            zenModeRepository.updateMode(ZenMode.MANUAL_DND_MODE_ID) {
                TestModeBuilder(it)
                    .setIconResId(DND_DRAWABLE_ID)
                    .setActive(true)
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            }
            assertThat(message?.message).isEqualTo("Notifications paused by Do Not Disturb")
            assertThat(message?.icon?.resId).isEqualTo(DND_DRAWABLE_ID)

            zenModeRepository.addMode(
                TestModeBuilder()
                    .setPackage("android")
                    .setId("Bedtime")
                    .setName("Bedtime")
                    .setIconResId(BEDTIME_DRAWABLE_ID)
                    .setActive(true)
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            )
            assertThat(message?.message)
                .isEqualTo("Notifications paused by Do Not Disturb and one other mode")
            assertThat(message?.icon?.resId).isEqualTo(DND_DRAWABLE_ID)

            zenModeRepository.addMode(
                TestModeBuilder()
                    .setPackage("android")
                    .setId("Theater")
                    .setName("Theater")
                    .setIconResId(THEATER_DRAWABLE_ID)
                    .setActive(true)
                    .setVisualEffect(VISUAL_EFFECT_NOTIFICATION_LIST, /* allowed= */ false)
                    .build()
            )
            assertThat(message?.message)
                .isEqualTo("Notifications paused by Do Not Disturb and 2 other modes")
            assertThat(message?.icon?.resId).isEqualTo(DND_DRAWABLE_ID)

            zenModeRepository.deactivateMode(ZenMode.MANUAL_DND_MODE_ID)
            zenModeRepository.deactivateMode("Bedtime")
            assertThat(message?.message).isEqualTo("Notifications paused by Theater")
            assertThat(message?.icon?.resId).isEqualTo(THEATER_DRAWABLE_ID)
        }

    @Test
    @DisableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun footer_isVisibleWhenSeenNotifsAreFilteredOut() =
        kosmos.runTest {
            val footerVisible by collectLastValue(underTest.footer.isVisible)
@@ -194,6 +289,17 @@ class EmptyShadeViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
            assertThat(footerVisible).isTrue()
        }

    @Test
    @EnableFlags(ShowIconInEmptyShade.FLAG_NAME)
    fun message_reflectsFilteredOutSeenNotifs() =
        kosmos.runTest {
            val message by collectLastValue(underTest.message)

            activeNotificationListRepository.hasFilteredOutSeenNotifications.value = true
            assertThat(message?.message).isEqualTo("Unlock to see older notifications")
            assertThat(message?.icon?.resId).isEqualTo(R.drawable.ic_friction_lock_closed)
        }

    @Test
    fun onClick_whenHistoryDisabled_leadsToSettingsPage() =
        kosmos.runTest {
+10 −0
Original line number Diff line number Diff line
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="960"
    android:viewportHeight="960"
    android:tint="?attr/colorControlNormal">
  <path
      android:fillColor="@android:color/white"
      android:pathData="M280,840L280,760L440,760L440,636Q391,625 352.5,594.5Q314,564 296,518Q221,509 170.5,452.5Q120,396 120,320L120,280Q120,247 143.5,223.5Q167,200 200,200L280,200L280,120L680,120L680,200L760,200Q793,200 816.5,223.5Q840,247 840,280L840,320Q840,396 789.5,452.5Q739,509 664,518Q646,564 607.5,594.5Q569,625 520,636L520,760L680,760L680,840L280,840ZM280,432L280,280L200,280L200,320Q200,358 222,388.5Q244,419 280,432ZM680,432Q716,419 738,388.5Q760,358 760,320L760,280L680,280L680,432Z"/>
</vector>
+55 −0
Original line number Diff line number Diff line
<!--
  ~ Copyright (C) 2025 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
  -->

<!-- This layout replaces status_bar_no_notifications when ShowIconInEmptyShade is turned on. -->
<!-- Extends FrameLayout -->
<com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeIconView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="gone">

    <LinearLayout
        android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:orientation="vertical"
        android:paddingVertical="@dimen/empty_shade_vertical_padding"
        android:paddingHorizontal="@dimen/empty_shade_horizontal_padding">

        <ImageView
            android:id="@id/icon"
            android:layout_width="@dimen/empty_shade_icon_size"
            android:layout_height="@dimen/empty_shade_icon_size"
            android:layout_marginBottom="@dimen/empty_shade_icon_bottom_margin"
            android:scaleType="fitCenter"
            app:tint="@androidprv:color/materialColorOnSurface"
            android:importantForAccessibility="no"
            android:src="@drawable/ic_trophy"></ImageView>

        <TextView
            android:id="@+id/text"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/empty_shade_text"
            android:textAppearance="@style/TextAppearance.NotificationShadeText" />
    </LinearLayout>
</com.android.systemui.statusbar.notification.emptyshade.ui.view.EmptyShadeIconView>
+8 −0
Original line number Diff line number Diff line
@@ -593,6 +593,14 @@

    <dimen name="notifications_unseen_footer_icon_size">16dp</dimen>

    <!-- The size of the icon shown in the shade when there are no notifications -->
    <dimen name="empty_shade_icon_size">32dp</dimen>
    <!-- The spacing between the icon and the text shown in the shade when there are no
         notifications. -->
    <dimen name="empty_shade_icon_bottom_margin">16dp</dimen>
    <dimen name="empty_shade_vertical_padding">32dp</dimen>
    <dimen name="empty_shade_horizontal_padding">16dp</dimen>

    <!-- Height of the status bar header bar when on Keyguard -->
    <dimen name="status_bar_header_height_keyguard">@dimen/status_bar_height</dimen>

Loading