@@ -2,6 +2,7 @@ package app.revanced.patches.shared.layout.branding
22
33import app.revanced.patcher.Fingerprint
44import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
5+ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
56import app.revanced.patcher.patch.PatchException
67import app.revanced.patcher.patch.ResourcePatch
78import app.revanced.patcher.patch.ResourcePatchBuilder
@@ -12,14 +13,24 @@ import app.revanced.patcher.patch.stringOption
1213import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
1314import app.revanced.patches.all.misc.resources.addResources
1415import app.revanced.patches.all.misc.resources.addResourcesPatch
16+ import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
1517import app.revanced.patches.shared.misc.settings.preference.BasePreferenceScreen
1618import app.revanced.patches.shared.misc.settings.preference.ListPreference
1719import app.revanced.util.ResourceGroup
1820import app.revanced.util.Utils.trimIndentMultiline
21+ import app.revanced.util.addInstructionsAtControlFlowLabel
1922import app.revanced.util.copyResources
2023import app.revanced.util.findElementByAttributeValueOrThrow
24+ import app.revanced.util.findInstructionIndicesReversedOrThrow
25+ import app.revanced.util.getReference
26+ import app.revanced.util.indexOfFirstInstructionOrThrow
27+ import app.revanced.util.indexOfFirstInstructionReversedOrThrow
2128import app.revanced.util.removeFromParent
2229import app.revanced.util.returnEarly
30+ import com.android.tools.smali.dexlib2.Opcode
31+ import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
32+ import com.android.tools.smali.dexlib2.iface.reference.FieldReference
33+ import com.android.tools.smali.dexlib2.iface.reference.TypeReference
2334import org.w3c.dom.Element
2435import org.w3c.dom.NodeList
2536import java.io.File
@@ -47,13 +58,15 @@ private const val LAUNCHER_RESOURCE_NAME_PREFIX = "revanced_launcher_"
4758private const val LAUNCHER_ADAPTIVE_BACKGROUND_PREFIX = " revanced_adaptive_background_"
4859private const val LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX = " revanced_adaptive_foreground_"
4960private const val LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX = " revanced_adaptive_monochrome_"
61+ private const val NOTIFICATION_ICON_SMALL = " revanced_notification_icon_small"
5062
5163private val USER_CUSTOM_ADAPTIVE_FILE_NAMES = arrayOf(
5264 " $LAUNCHER_ADAPTIVE_BACKGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .png" ,
5365 " $LAUNCHER_ADAPTIVE_FOREGROUND_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .png"
5466)
5567
56- private const val USER_CUSTOM_MONOCHROME_NAME = " $LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .xml"
68+ private const val USER_CUSTOM_MONOCHROME_FILE_NAME = " $LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .xml"
69+ private const val USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME = " ${NOTIFICATION_ICON_SMALL } _$CUSTOM_USER_ICON_STYLE_NAME .xml"
5770
5871internal const val EXTENSION_CLASS_DESCRIPTOR = " Lapp/revanced/extension/shared/patches/CustomBrandingPatch;"
5972
@@ -96,16 +109,17 @@ internal fun baseCustomBrandingPatch(
96109 Each of the folders must contain all of the following files:
97110 ${USER_CUSTOM_ADAPTIVE_FILE_NAMES .joinToString(" \n " )}
98111
99- Optionally, the path can contain a 'drawable' folder with the monochrome icon file:
100- $USER_CUSTOM_MONOCHROME_NAME
112+ Optionally, the path contains a 'drawable' folder with any of the monochrome icon files:
113+ $USER_CUSTOM_MONOCHROME_FILE_NAME
114+ $USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
101115 """ .trimIndentMultiline()
102116 )
103117
104118 block()
105119
106120 dependsOn(
107121 addResourcesPatch,
108-
122+ resourceMappingPatch,
109123 bytecodePatch {
110124 execute {
111125 mainActivityOnCreateFingerprint.method.addInstruction(
@@ -114,6 +128,34 @@ internal fun baseCustomBrandingPatch(
114128 )
115129
116130 numberOfPresetAppNamesExtensionFingerprint.method.returnEarly(numberOfPresetAppNames)
131+
132+ notificationFingerprint.method.apply {
133+ // Find the field name of the notification builder. Field is an Object type.
134+ val builderCastIndex = indexOfFirstInstructionOrThrow {
135+ val reference = getReference<TypeReference >()
136+ opcode == Opcode .CHECK_CAST &&
137+ reference?.type == " Landroid/app/Notification\$ Builder;"
138+ }
139+ val getBuilderIndex = indexOfFirstInstructionReversedOrThrow(builderCastIndex) {
140+ getReference<FieldReference >()?.type == " Ljava/lang/Object;"
141+ }
142+ val builderFieldName = getInstruction<ReferenceInstruction >(getBuilderIndex)
143+ .getReference<FieldReference >()
144+
145+ findInstructionIndicesReversedOrThrow(
146+ Opcode .RETURN_VOID
147+ ).forEach { index ->
148+ addInstructionsAtControlFlowLabel(
149+ index,
150+ """
151+ move-object/from16 v0, p0
152+ iget-object v0, v0, $builderFieldName
153+ check-cast v0, Landroid/app/Notification${' $' } Builder;
154+ invoke-static { v0 }, $EXTENSION_CLASS_DESCRIPTOR ->setNotificationIcon(Landroid/app/Notification${' $' } Builder;)V
155+ """
156+ )
157+ }
158+ }
117159 }
118160 }
119161 )
@@ -176,20 +218,27 @@ internal fun baseCustomBrandingPatch(
176218 )
177219 }
178220
179- // Copy template user icon, because the aliases must be added even if no user icon is provided.
180221 copyResources(
181222 " custom-branding" ,
223+ // ReVanced notification icon (all branding styles use the same icon).
182224 ResourceGroup (
183- " mipmap-anydpi " ,
184- " $LAUNCHER_RESOURCE_NAME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .xml" ,
225+ " drawable " ,
226+ " $NOTIFICATION_ICON_SMALL .xml"
185227 ),
228+
229+ // Copy template user icon, because the aliases must be added even if no user icon is provided.
186230 ResourceGroup (
187231 " drawable" ,
188- " $LAUNCHER_ADAPTIVE_MONOCHROME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .xml" ,
232+ USER_CUSTOM_MONOCHROME_FILE_NAME ,
233+ USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
234+ ),
235+ ResourceGroup (
236+ " mipmap-anydpi" ,
237+ " $LAUNCHER_RESOURCE_NAME_PREFIX$CUSTOM_USER_ICON_STYLE_NAME .xml" ,
189238 )
190239 )
191240
192- // Copy template icon png files.
241+ // Copy template icon files.
193242 mipmapDirectories.forEach { dpi ->
194243 copyResources(
195244 " custom-branding" ,
@@ -375,15 +424,20 @@ internal fun baseCustomBrandingPatch(
375424 }
376425 }
377426
378- // Copy monochrome if it provided.
379- val monochromeRelativePath = " drawable/$USER_CUSTOM_MONOCHROME_NAME "
380- val monochromeFile = iconPathFile.resolve(monochromeRelativePath)
381- if (monochromeFile.exists()) {
382- monochromeFile.copyTo(
383- target = resourceDirectory.resolve(monochromeRelativePath),
384- overwrite = true
385- )
386- copiedFiles = true
427+ // Copy monochrome and small notification icon if it provided.
428+ arrayOf(
429+ USER_CUSTOM_MONOCHROME_FILE_NAME ,
430+ USER_CUSTOM_NOTIFICATION_ICON_FILE_NAME
431+ ).forEach { fileName ->
432+ val relativePath = " drawable/$fileName "
433+ val file = iconPathFile.resolve(relativePath)
434+ if (file.exists()) {
435+ file.copyTo(
436+ target = resourceDirectory.resolve(relativePath),
437+ overwrite = true
438+ )
439+ copiedFiles = true
440+ }
387441 }
388442
389443 if (! copiedFiles) {
0 commit comments