1 /*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.systemui.statusbar.notification.collection
18
19 import android.app.Notification
20 import android.app.NotificationChannel
21 import android.app.NotificationManager.IMPORTANCE_DEFAULT
22 import android.app.NotificationManager.IMPORTANCE_LOW
23 import android.app.PendingIntent
24 import android.app.Person
25 import android.content.Intent
26 import android.content.applicationContext
27 import android.graphics.Bitmap
28 import android.graphics.drawable.Icon
29 import com.android.systemui.activity.EmptyTestActivity
30 import com.android.systemui.kosmos.Kosmos
31 import com.android.systemui.res.R
32 import com.android.systemui.statusbar.notification.icon.IconPack
33 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.PeopleNotificationType
34 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
35 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
36 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
37 import com.android.systemui.statusbar.notification.promoted.setPromotedContent
38 import org.mockito.kotlin.mock
39
setIconPackWithMockIconViewsnull40 fun Kosmos.setIconPackWithMockIconViews(entry: NotificationEntry) {
41 entry.icons =
42 IconPack.buildPack(
43 /* statusBarIcon = */ mock(),
44 /* statusBarChipIcon = */ mock(),
45 /* shelfIcon = */ mock(),
46 /* aodIcon = */ mock(),
47 /* source = */ null,
48 )
49 }
50
buildPromotedOngoingEntrynull51 fun Kosmos.buildPromotedOngoingEntry(
52 block: NotificationEntryBuilder.() -> Unit = {}
53 ): NotificationEntry =
54 buildNotificationEntry(tag = "ron", promoted = true, style = null, block = block)
55
buildOngoingCallEntrynull56 fun Kosmos.buildOngoingCallEntry(
57 promoted: Boolean = false,
58 block: NotificationEntryBuilder.() -> Unit = {},
59 ): NotificationEntry =
60 buildNotificationEntry(
61 tag = "call",
62 promoted = promoted,
63 style = makeOngoingCallStyle(),
64 block = block,
65 )
66
buildNotificationEntrynull67 fun Kosmos.buildNotificationEntry(
68 tag: String? = null,
69 promoted: Boolean = false,
70 style: Notification.Style? = null,
71 block: NotificationEntryBuilder.() -> Unit = {},
72 ): NotificationEntry =
73 NotificationEntryBuilder()
<lambda>null74 .apply {
75 setTag(tag)
76 setFlag(applicationContext, Notification.FLAG_PROMOTED_ONGOING, promoted)
77 modifyNotification(applicationContext)
78 .setSmallIcon(Icon.createWithContentUri("content://null"))
79 .setStyle(style)
80 }
81 .apply(block)
82 .build()
<lambda>null83 .also {
84 setIconPackWithMockIconViews(it)
85 if (promoted) setPromotedContent(it)
86 }
87
makeOngoingCallStylenull88 private fun Kosmos.makeOngoingCallStyle(): Notification.CallStyle {
89 val pendingIntent =
90 PendingIntent.getBroadcast(
91 applicationContext,
92 0,
93 Intent("action"),
94 PendingIntent.FLAG_IMMUTABLE,
95 )
96 val person = Person.Builder().setName("person").build()
97 return Notification.CallStyle.forOngoingCall(person, pendingIntent)
98 }
99
makeMessagingStyleNotificationnull100 private fun Kosmos.makeMessagingStyleNotification(): Notification.Builder {
101 val personIcon = Icon.createWithBitmap(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
102 val person = Person.Builder().setIcon(personIcon).setName("Person").build()
103 val message = Notification.MessagingStyle.Message("Message!", 4323, person)
104 val bubbleIntent =
105 PendingIntent.getActivity(
106 applicationContext,
107 0,
108 Intent(applicationContext, EmptyTestActivity::class.java),
109 PendingIntent.FLAG_MUTABLE,
110 )
111
112 return Notification.Builder(applicationContext, "channelId")
113 .setSmallIcon(R.drawable.ic_person)
114 .setContentTitle("Title")
115 .setContentText("Text")
116 .setStyle(Notification.MessagingStyle(person).addMessage(message))
117 .setBubbleMetadata(
118 Notification.BubbleMetadata.Builder(
119 bubbleIntent,
120 Icon.createWithResource(applicationContext, R.drawable.android),
121 )
122 .setDeleteIntent(mock<PendingIntent>())
123 .setDesiredHeight(314)
124 .setAutoExpandBubble(false)
125 .build()
126 )
127 }
128
makeEntryOfPeopleTypenull129 fun Kosmos.makeEntryOfPeopleType(@PeopleNotificationType type: Int): NotificationEntryBuilder {
130 val channel = NotificationChannel("messages", "messages", IMPORTANCE_DEFAULT)
131 channel.isImportantConversation = (type == TYPE_IMPORTANT_PERSON)
132 channel.setConversationId("parent", "convo")
133
134 val entry =
135 NotificationEntryBuilder().apply {
136 updateRanking {
137 it.setIsConversation(type != TYPE_NON_PERSON)
138 it.setShortcutInfo(if (type >= TYPE_FULL_PERSON) mock() else null)
139 it.setChannel(channel)
140 }
141 setNotification(makeMessagingStyleNotification().build())
142 }
143 return entry
144 }
145
Kosmosnull146 fun Kosmos.makeClassifiedConversation(channelId: String): NotificationEntry {
147 val channel = NotificationChannel(channelId, channelId, IMPORTANCE_LOW)
148 val entry =
149 NotificationEntryBuilder()
150 .updateRanking {
151 it.setIsConversation(true)
152 it.setShortcutInfo(mock())
153 it.setChannel(channel)
154 }
155 .build()
156 return entry
157 }