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

Commit edca1d02 authored by Pawan Wagh's avatar Pawan Wagh Committed by Android (Google) Code Review
Browse files

Merge changes from topic "revert-33994252-bundle_header_tweaks-SSWNELMVBL" into main

* changes:
  Revert "Refactor AppIconProvider to fix bugs"
  Revert "Bundle header tweaks"
parents 1c61b5e6 9d953996
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -36,6 +37,7 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
@@ -223,8 +225,7 @@ private fun ContentScope.BundlePreviewIcons(
    check(previewDrawables.isNotEmpty())
    val iconSize = 32.dp

    // The design stroke width is 2.5dp but there is a ~4% padding inside app icons; ~1.25dp here.
    val borderWidth = 1.25.dp
    val borderWidth = 2.5.dp
    HalfOverlappingReversedRow(
        modifier =
            modifier.graphicsLayer {
@@ -274,10 +275,14 @@ private fun PreviewIcon(drawable: Drawable, modifier: Modifier = Modifier, borde
                drawContent()
            }
    ) {
        val surfaceColor = notificationElementSurfaceColor()
        Image(
            painter = rememberDrawablePainter(drawable),
            contentDescription = null,
            modifier = Modifier.fillMaxSize(),
            modifier =
                Modifier.fillMaxSize()
                    .clip(CircleShape)
                    .background(color = surfaceColor, shape = CircleShape),
            contentScale = ContentScale.Fit,
        )
    }
+0 −58
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.
 */

package com.android.systemui.notifications.ui.composable.row

import androidx.annotation.FloatRange
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color

@Composable
@ReadOnlyComposable
fun notificationProtectionColor(): Color {
    // Per android.app.Notification.Colors, this is a 90% blend
    // of materialColorOnSurface over materialColorSurfaceContainerHigh
    val background = MaterialTheme.colorScheme.surfaceContainerHigh
    val primaryText = MaterialTheme.colorScheme.onSurface
    return blendARGB(primaryText, background, 0.9f)
}

/**
 * Blend between two ARGB colors using the given ratio.
 *
 * A blend ratio of 0.0 will result in [color1], 0.5 will give an even blend, 1.0 will result in
 * [color2].
 *
 * @param color1 the first ARGB color
 * @param color2 the second ARGB color
 * @param ratio the blend ratio of [color1] to [color2]
 * @see [com.android.internal.graphics.ColorUtils.blendARGB]
 */
private fun blendARGB(
    color1: Color,
    color2: Color,
    @FloatRange(from = 0.0, to = 1.0) ratio: Float,
): Color {
    val inverseRatio = 1 - ratio
    return Color(
        red = color1.red * inverseRatio + color2.red * ratio,
        green = color1.green * inverseRatio + color2.green * ratio,
        blue = color1.blue * inverseRatio + color2.blue * ratio,
        alpha = color1.alpha * inverseRatio + color2.alpha * ratio,
    )
}
+15 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.notifications.ui.composable.row
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
@@ -32,6 +33,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -66,8 +68,8 @@ object NotificationRowPrimitives {
/** The Icon displayed at the start of any notification row. */
@Composable
fun BundleIcon(@DrawableRes drawable: Int?, modifier: Modifier = Modifier) {
    val iconBackground = notificationProtectionColor()
    Box(modifier = modifier.size(40.dp).background(color = iconBackground, shape = CircleShape)) {
    val surfaceColor = notificationElementSurfaceColor()
    Box(modifier = modifier.size(40.dp).background(color = surfaceColor, shape = CircleShape)) {
        if (drawable == null) return@Box
        Image(
            painter = painterResource(drawable),
@@ -113,7 +115,7 @@ fun ContentScope.ExpansionControl(

@Composable
private fun ContentScope.PillBackground(modifier: Modifier = Modifier) {
    val surfaceColor = notificationProtectionColor()
    val surfaceColor = notificationElementSurfaceColor()
    // Needs to be a shared element so it does not overlap while animating
    ElementWithValues(NotificationRowPrimitives.Elements.PillBackground, modifier) {
        Box(
@@ -128,6 +130,16 @@ private fun ContentScope.PillBackground(modifier: Modifier = Modifier) {
    }
}

@Composable
@ReadOnlyComposable
fun notificationElementSurfaceColor(): Color {
    return if (isSystemInDarkTheme()) {
        Color.White.copy(alpha = 0.15f)
    } else {
        MaterialTheme.colorScheme.surfaceContainerHighest
    }
}

@Composable
private fun ContentScope.Chevron(collapsed: Boolean, color: Color, modifier: Modifier = Modifier) {
    val key = NotificationRowPrimitives.Elements.Chevron
+14 −2
Original line number Diff line number Diff line
@@ -125,7 +125,10 @@ class NotificationInfoTest : SysuiTestCase() {

        // Inflate the layout
        val inflater = LayoutInflater.from(mContext)
        underTest = inflater.inflate(R.layout.notification_info, null) as NotificationInfo
        val layoutId =
            if (Flags.notificationsRedesignTemplates()) R.layout.notification_2025_info
            else R.layout.notification_info
        underTest = inflater.inflate(layoutId, null) as NotificationInfo

        underTest.setGutsParent(mock<NotificationGuts>())

@@ -228,7 +231,16 @@ class NotificationInfoTest : SysuiTestCase() {
    @EnableFlags(Flags.FLAG_NOTIFICATIONS_REDESIGN_TEMPLATES)
    fun testBindNotification_SetsPackageIcon_flagOn() {
        val iconDrawable = mock<Drawable>()
        whenever(mockAppIconProvider.getOrFetchAppIcon(anyOrNull(), anyOrNull(), anyOrNull()))
        whenever(mockIconStyleProvider.shouldShowWorkProfileBadge(anyOrNull(), anyOrNull()))
            .thenReturn(false)
        whenever(
                mockAppIconProvider.getOrFetchAppIcon(
                    anyOrNull(),
                    anyOrNull(),
                    anyBoolean(),
                    anyBoolean(),
                )
            )
            .thenReturn(iconDrawable)
        bindNotification()
        val iconView = underTest.findViewById<ImageView>(R.id.pkg_icon)
+26 −16
Original line number Diff line number Diff line
@@ -18,10 +18,10 @@

package com.android.systemui.statusbar.notification.row.domain.interactor

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.UserHandle
import android.platform.test.annotations.EnableFlags
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MotionScheme
@@ -55,6 +55,7 @@ import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.mock
import org.mockito.kotlin.whenever
import platform.test.motion.compose.runMonotonicClockTest
@@ -100,8 +101,9 @@ class BundleInteractorTest : SysuiTestCase() {
            whenever(
                    kosmos.mockAppIconProvider.getOrFetchAppIcon(
                        any<String>(),
                        any<UserHandle>(),
                        any<String>(),
                        any<Context>(),
                        eq(false),
                        eq(false),
                    )
                )
                .thenReturn(drawable1)
@@ -117,7 +119,7 @@ class BundleInteractorTest : SysuiTestCase() {

            // Assert
            verify(kosmos.mockAppIconProvider, times(4))
                .getOrFetchAppIcon(any<String>(), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(any<String>(), any<Context>(), eq(false), eq(false))

            assertThat(result).hasSize(3)
            assertThat(result).containsExactly(drawable1, drawable2, drawable3).inOrder()
@@ -142,16 +144,18 @@ class BundleInteractorTest : SysuiTestCase() {
            whenever(
                    kosmos.mockAppIconProvider.getOrFetchAppIcon(
                        eq("app1"),
                        any<UserHandle>(),
                        any<String>(),
                        anyOrNull<Context>(),
                        eq(false),
                        eq(false),
                    )
                )
                .thenReturn(drawable1)
            whenever(
                    kosmos.mockAppIconProvider.getOrFetchAppIcon(
                        eq("app2"),
                        any<UserHandle>(),
                        any<String>(),
                        anyOrNull<Context>(),
                        eq(false),
                        eq(false),
                    )
                )
                .thenReturn(drawable2)
@@ -166,9 +170,9 @@ class BundleInteractorTest : SysuiTestCase() {
            // Assert
            assertThat(result).containsExactly(drawable1, drawable2).inOrder()
            verify(kosmos.mockAppIconProvider)
                .getOrFetchAppIcon(eq("app1"), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(eq("app1"), anyOrNull<Context>(), eq(false), eq(false))
            verify(kosmos.mockAppIconProvider)
                .getOrFetchAppIcon(eq("app2"), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(eq("app2"), anyOrNull<Context>(), eq(false), eq(false))
        }

    @Test
@@ -197,8 +201,9 @@ class BundleInteractorTest : SysuiTestCase() {
            whenever(
                    kosmos.mockAppIconProvider.getOrFetchAppIcon(
                        eq("new_app"),
                        any<UserHandle>(),
                        any<String>(),
                        anyOrNull<Context>(),
                        eq(false),
                        eq(false),
                    )
                )
                .thenReturn(drawable3)
@@ -213,11 +218,16 @@ class BundleInteractorTest : SysuiTestCase() {
            // Assert
            assertThat(result).containsExactly(drawable3)
            verify(kosmos.mockAppIconProvider, times(0))
                .getOrFetchAppIcon(eq("old_app"), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(eq("old_app"), anyOrNull<Context>(), eq(false), eq(false))
            verify(kosmos.mockAppIconProvider, times(0))
                .getOrFetchAppIcon(eq("at_collapse_app"), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(
                    eq("at_collapse_app"),
                    anyOrNull<Context>(),
                    eq(false),
                    eq(false),
                )
            verify(kosmos.mockAppIconProvider)
                .getOrFetchAppIcon(eq("new_app"), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(eq("new_app"), anyOrNull<Context>(), eq(false), eq(false))
        }

    @Test
@@ -243,7 +253,7 @@ class BundleInteractorTest : SysuiTestCase() {
            // Assert
            assertThat(result).isEmpty()
            verify(kosmos.mockAppIconProvider, times(0))
                .getOrFetchAppIcon(anyString(), any<UserHandle>(), any<String>())
                .getOrFetchAppIcon(anyString(), anyOrNull<Context>(), eq(false), eq(false))
        }

    @Test
Loading