chore: lint code

This commit is contained in:
inotia00 2024-03-23 00:02:02 +09:00
parent 49727dfb3a
commit 3d8e3bb0be
11 changed files with 146 additions and 185 deletions

View File

@ -69,7 +69,7 @@ object SharedResourceIdPatch : ResourcePatch() {
MiniPlayerPlayPauseReplayButton = find(ID, "mini_player_play_pause_replay_button")
MusicMenuLikeButtons = find(LAYOUT, "music_menu_like_buttons")
MusicNotifierShelf = find(LAYOUT, "music_notifier_shelf")
MusicTastebuilderShelf = find(LAYOUT, "music_tastebuilder_shelf")
MusicTasteBuilderShelf = find(LAYOUT, "music_tastebuilder_shelf")
NamesInactiveAccountThumbnailSize = find(DIMEN, "names_inactive_account_thumbnail_size")
OfflineSettingsMenuItem = find(ID, "offline_settings_menu_item")
PlayerCastMediaRouteButton = find(LAYOUT, "player_cast_media_route_button")

View File

@ -9,8 +9,8 @@ import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.AutoMotiveFingerprint
import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarButtonViewFingerprint
import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarEnumFingerprint
import app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints.PivotBarShortsButtonViewFingerprint
import app.revanced.patches.youtube.utils.fingerprints.PivotBarCreateButtonViewFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.NAVIGATION
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
@ -80,7 +80,7 @@ object NavigationButtonsPatch : BytecodePatch(
with(
arrayOf(
PivotBarEnumFingerprint,
PivotBarShortsButtonViewFingerprint
PivotBarButtonViewFingerprint
).onEach {
it.resolve(
context,

View File

@ -3,10 +3,10 @@ package app.revanced.patches.youtube.navigation.navigationbuttons.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
object PivotBarShortsButtonViewFingerprint : MethodFingerprint(
object PivotBarButtonViewFingerprint : MethodFingerprint(
opcodes = listOf(
Opcode.INVOKE_VIRTUAL_RANGE,
Opcode.MOVE_RESULT_OBJECT, // target reference
Opcode.GOTO,
null,
)
)

View File

@ -1,4 +1,4 @@
package app.revanced.patches.youtube.video.quality.fingerprints
package app.revanced.patches.youtube.utils.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint

View File

@ -7,31 +7,30 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.extensions.InstructionExtensions.replaceInstruction
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.Patch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.youtube.utils.fingerprints.SeekbarFingerprint
import app.revanced.patches.youtube.utils.fingerprints.SeekbarOnDrawFingerprint
import app.revanced.patches.youtube.utils.fingerprints.TotalTimeFingerprint
import app.revanced.patches.youtube.utils.fingerprints.YouTubeControlsOverlayFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH
import app.revanced.patches.youtube.utils.overridespeed.OverrideSpeedHookPatch
import app.revanced.patches.youtube.utils.playercontrols.PlayerControlsPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.InsetOverlayViewLayout
import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch.TotalTime
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.RectangleFieldInvalidatorFingerprint
import app.revanced.patches.youtube.utils.sponsorblock.fingerprints.SegmentPlaybackControllerFingerprint
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
import app.revanced.patches.youtube.utils.videoid.withoutshorts.VideoIdWithoutShortsPatch
import app.revanced.util.exception
import app.revanced.util.getTargetIndex
import app.revanced.util.getTargetIndexWithFieldReferenceTypeReversed
import app.revanced.util.getTargetIndexWithMethodReferenceName
import app.revanced.util.getTargetIndexWithMethodReferenceNameReversed
import app.revanced.util.getWideLiteralInstructionIndex
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.builder.BuilderInstruction
import com.android.tools.smali.dexlib2.builder.instruction.BuilderInstruction3rc
import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.instruction.formats.Instruction35c
import com.android.tools.smali.dexlib2.iface.reference.FieldReference
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
@Patch(
dependencies = [
@ -50,179 +49,123 @@ object SponsorBlockBytecodePatch : BytecodePatch(
YouTubeControlsOverlayFingerprint
)
) {
private const val INTEGRATIONS_SPONSOR_BLOCK_PATH =
"$INTEGRATIONS_PATH/sponsorblock"
private const val INTEGRATIONS_SPONSOR_BLOCK_UI_PATH =
"$INTEGRATIONS_SPONSOR_BLOCK_PATH/ui"
private const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR =
"$INTEGRATIONS_SPONSOR_BLOCK_PATH/SegmentPlaybackController;"
override fun execute(context: BytecodeContext) {
/**
* Hook the video time methods
*/
VideoIdPatch.apply {
// Hook the video time method
videoTimeHook(
INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR,
INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR,
"setVideoTime"
)
// Initialize SponsorBlock
onCreateHook(
INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR,
INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR,
"initialize"
)
}
val seekBarClass = SeekbarFingerprint.result?.mutableClass
?: throw SeekbarFingerprint.exception
SeekbarOnDrawFingerprint.resolve(context, seekBarClass)
RectangleFieldInvalidatorFingerprint.resolve(context, seekBarClass)
/**
* Seekbar drawing
*/
SeekbarFingerprint.result?.mutableClass?.let { mutableClass ->
insertMethod = SeekbarOnDrawFingerprint.also {
it.resolve(
context,
mutableClass
)
}.result?.mutableMethod
?: throw SeekbarOnDrawFingerprint.exception
insertInstructions = insertMethod.implementation!!.instructions
} ?: throw SeekbarFingerprint.exception
SeekbarOnDrawFingerprint.result?.mutableMethod?.apply {
// Get left and right of seekbar rectangle
val moveObjectIndex = getTargetIndex(Opcode.MOVE_OBJECT_FROM16)
/**
* Get left and right of seekbar rectangle
*/
val moveRectangleToRegisterIndex = insertInstructions.indexOfFirst {
it.opcode == Opcode.MOVE_OBJECT_FROM16
}
insertMethod.addInstruction(
moveRectangleToRegisterIndex + 1,
"invoke-static/range {p0 .. p0}, " +
"$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
)
for ((index, instruction) in insertInstructions.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_STATIC) continue
val invokeInstruction = insertMethod.getInstruction<Instruction35c>(index)
if ((invokeInstruction.reference as MethodReference).name != "round") continue
val insertIndex = index + 2
insertMethod.addInstruction(
insertIndex,
"invoke-static {v${invokeInstruction.registerC}}, " +
"$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
addInstruction(
moveObjectIndex + 1,
"invoke-static/range {p0 .. p0}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V"
)
break
}
// Set seekbar thickness
val roundIndex = getTargetIndexWithMethodReferenceName("round") + 1
val roundRegister = getInstruction<OneRegisterInstruction>(roundIndex).registerA
/**
* Draw segment
*/
for ((index, instruction) in insertInstructions.withIndex()) {
if (instruction.opcode != Opcode.INVOKE_VIRTUAL_RANGE) continue
val invokeInstruction = instruction as BuilderInstruction3rc
if ((invokeInstruction.reference as MethodReference).name != "restore") continue
val drawSegmentInstructionInsertIndex = index - 1
val (canvasInstance, centerY) =
insertMethod.getInstruction<FiveRegisterInstruction>(
drawSegmentInstructionInsertIndex
).let { it.registerC to it.registerE }
insertMethod.addInstruction(
drawSegmentInstructionInsertIndex,
"invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V"
addInstruction(
roundIndex + 1,
"invoke-static {v$roundRegister}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V"
)
break
// Draw segment
val drawCircleIndex = getTargetIndexWithMethodReferenceNameReversed("drawCircle")
val drawCircleInstruction = getInstruction<FiveRegisterInstruction>(drawCircleIndex)
addInstruction(
drawCircleIndex,
"invoke-static {v${drawCircleInstruction.registerC}, v${drawCircleInstruction.registerE}}, " +
"$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V"
)
} ?: throw SeekbarOnDrawFingerprint.exception
// Voting & Shield button
arrayOf("CreateSegmentButtonController;", "VotingButtonController;").forEach { className ->
PlayerControlsPatch.initializeSB("$INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/$className")
PlayerControlsPatch.injectVisibility("$INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/$className")
}
/**
* Voting & Shield button
*/
arrayOf("CreateSegmentButtonController", "VotingButtonController").forEach {
PlayerControlsPatch.initializeSB("$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/$it;")
PlayerControlsPatch.injectVisibility("$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/$it;")
}
/**
* Append the new time to the player layout
*/
// Append timestamp
TotalTimeFingerprint.result?.let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(TotalTime) + 2
val targetIndex = getTargetIndexWithMethodReferenceName("getString") + 1
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
addInstructions(
targetIndex + 1, """
invoke-static {v$targetRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String;
invoke-static {v$targetRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String;
move-result-object v$targetRegister
"""
)
}
} ?: throw TotalTimeFingerprint.exception
/**
* Initialize the SponsorBlock view
*/
// Initialize the SponsorBlock view
YouTubeControlsOverlayFingerprint.result?.let {
it.mutableMethod.apply {
val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout) + 3
val targetRegister = getInstruction<OneRegisterInstruction>(targetIndex).registerA
val targetIndex = getWideLiteralInstructionIndex(InsetOverlayViewLayout)
val checkCastIndex = getTargetIndex(targetIndex, Opcode.CHECK_CAST)
val targetRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
addInstruction(
targetIndex + 1,
"invoke-static {v$targetRegister}, $INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/ui/SponsorBlockViewController;->initialize(Landroid/view/ViewGroup;)V"
checkCastIndex + 1,
"invoke-static {v$targetRegister}, $INTEGRATIONS_SPONSOR_BLOCK_UI_PATH/SponsorBlockViewController;->initialize(Landroid/view/ViewGroup;)V"
)
}
} ?: throw YouTubeControlsOverlayFingerprint.exception
// Replace strings
RectangleFieldInvalidatorFingerprint.result?.let { result ->
result.mutableMethod.apply {
val invalidateIndex = getTargetIndexWithMethodReferenceNameReversed("invalidate")
val rectangleIndex = getTargetIndexWithFieldReferenceTypeReversed(invalidateIndex + 1, "Landroid/graphics/Rect;")
val rectangleFieldName = (getInstruction<ReferenceInstruction>(rectangleIndex).reference as FieldReference).name
/**
* Replace strings
*/
SeekbarFingerprint.result?.mutableClass?.let { mutableClass ->
RectangleFieldInvalidatorFingerprint.also {
it.resolve(
context,
mutableClass
)
}.result?.let {
it.mutableMethod.apply {
val rectangleReference =
getInstruction<ReferenceInstruction>(implementation!!.instructions.count() - 3).reference
val rectangleFieldName = (rectangleReference as FieldReference).name
SegmentPlaybackControllerFingerprint.result?.let {
it.mutableMethod.apply {
val replaceIndex = it.scanResult.patternScanResult!!.startIndex
val replaceRegister =
getInstruction<OneRegisterInstruction>(replaceIndex).registerA
SegmentPlaybackControllerFingerprint.result?.let { result ->
result.mutableMethod.apply {
val replaceIndex = result.scanResult.patternScanResult!!.startIndex
val replaceRegister =
getInstruction<OneRegisterInstruction>(replaceIndex).registerA
replaceInstruction(
replaceIndex,
"const-string v$replaceRegister, \"$rectangleFieldName\""
)
}
} ?: throw SegmentPlaybackControllerFingerprint.exception
}
} ?: throw YouTubeControlsOverlayFingerprint.exception
replaceInstruction(
replaceIndex,
"const-string v$replaceRegister, \"$rectangleFieldName\""
)
}
} ?: throw SegmentPlaybackControllerFingerprint.exception
}
} ?: throw RectangleFieldInvalidatorFingerprint.exception
} ?: throw SeekbarFingerprint.exception
/**
* Inject VideoIdPatch
*/
VideoIdWithoutShortsPatch.injectCall("$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
// Inject VideoIdPatch
VideoIdWithoutShortsPatch.injectCall("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
}
private const val INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR =
"Lapp/revanced/integrations/youtube/sponsorblock"
private const val INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR =
"$INTEGRATIONS_BUTTON_CLASS_DESCRIPTOR/SegmentPlaybackController;"
private lateinit var insertMethod: MutableMethod
private lateinit var insertInstructions: List<BuilderInstruction>
}

View File

@ -1,23 +1,9 @@
package app.revanced.patches.youtube.utils.sponsorblock.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
object RectangleFieldInvalidatorFingerprint : MethodFingerprint(
object RectangleFieldInvalidatorFingerprint : MethodReferenceNameFingerprint(
returnType = "V",
customFingerprint = custom@{ methodDef, _ ->
val instructions = methodDef.implementation?.instructions!!
val instructionCount = instructions.count()
// the method has definitely more than 5 instructions
if (instructionCount < 5) return@custom false
val referenceInstruction =
instructions.elementAt(instructionCount - 2) // the second to last instruction
val reference =
((referenceInstruction as? ReferenceInstruction)?.reference as? MethodReference)
reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method
}
parameters = emptyList(),
reference = { "invalidate" }
)

View File

@ -2,6 +2,7 @@ package app.revanced.patches.youtube.utils.sponsorblock.fingerprints
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.patches.youtube.utils.integrations.Constants.INTEGRATIONS_PATH
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
@ -11,7 +12,7 @@ object SegmentPlaybackControllerFingerprint : MethodFingerprint(
parameters = listOf("Ljava/lang/Object;"),
opcodes = listOf(Opcode.CONST_STRING),
customFingerprint = { methodDef, _ ->
methodDef.definingClass == "Lapp/revanced/integrations/youtube/sponsorblock/SegmentPlaybackController;"
methodDef.definingClass == "$INTEGRATIONS_PATH/sponsorblock/SegmentPlaybackController;"
&& methodDef.name == "setSponsorBarRect"
}
)

View File

@ -1,27 +1,9 @@
package app.revanced.patches.youtube.video.hdr.fingerprints
import app.revanced.patcher.fingerprint.MethodFingerprint
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import app.revanced.util.fingerprint.MethodReferenceNameFingerprint
object HdrCapabilitiesFingerprint : MethodFingerprint(
object HdrCapabilitiesFingerprint : MethodReferenceNameFingerprint(
returnType = "Z",
parameters = listOf("I", "Landroid/view/Display;"),
customFingerprint = custom@{ methodDef, _ ->
if (methodDef.implementation == null)
return@custom false
for (instruction in methodDef.implementation!!.instructions) {
if (instruction.opcode != Opcode.INVOKE_VIRTUAL)
continue
val objectInstruction = instruction as ReferenceInstruction
if ((objectInstruction.reference as MethodReference).name != "getSupportedHdrTypes")
continue
return@custom true
}
return@custom false
}
reference = { "getSupportedHdrTypes" }
)

View File

@ -16,7 +16,7 @@ import app.revanced.patches.youtube.utils.settings.SettingsPatch
import app.revanced.patches.youtube.utils.settings.SettingsPatch.contexts
import app.revanced.patches.youtube.utils.videoid.general.VideoIdPatch
import app.revanced.patches.youtube.utils.videoid.withoutshorts.VideoIdWithoutShortsPatch
import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualitySetterFingerprint
import app.revanced.patches.youtube.utils.fingerprints.VideoQualitySetterFingerprint
import app.revanced.util.copyXmlNode
import app.revanced.util.exception
import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction

View File

@ -143,6 +143,15 @@ fun BytecodeContext.traverseClassHierarchy(
inline fun <reified T : Reference> Instruction.getReference() =
(this as? ReferenceInstruction)?.reference as? T
/**
* Get the index of the first [Instruction] that matches the predicate.
*
* @param predicate The predicate to match.
* @return The index of the first [Instruction] that matches the predicate.
*/
fun Method.indexOfFirstInstruction(predicate: Instruction.() -> Boolean) =
this.implementation!!.instructions.indexOfFirst(predicate)
fun MutableMethod.getTargetIndex(opcode: Opcode) = getTargetIndex(0, opcode)
fun MutableMethod.getTargetIndexReversed(opcode: Opcode) =
@ -220,6 +229,12 @@ fun MutableMethod.getTargetIndexWithMethodReferenceNameReversed(startIndex: Int,
return -1
}
fun MutableMethod.getTargetIndexWithReference(reference: String)
= getTargetIndexWithReference(0, reference)
fun MutableMethod.getTargetIndexWithReferenceReversed(reference: String)
= getTargetIndexWithReferenceReversed(implementation!!.instructions.size - 1, reference)
fun MutableMethod.getTargetIndexWithReference(startIndex: Int, reference: String) =
implementation!!.instructions.let {
startIndex + it.subList(startIndex, it.size - 1).indexOfFirst { instruction ->

View File

@ -0,0 +1,34 @@
package app.revanced.util.fingerprint
import app.revanced.patcher.fingerprint.MethodFingerprint
import app.revanced.util.containsMethodReferenceNameInstructionIndex
import com.android.tools.smali.dexlib2.Opcode
/**
* A fingerprint to resolve methods that contain a specific method reference name value.
*
* @param returnType The method's return type compared using String.startsWith.
* @param accessFlags The method's exact access flags using values of AccessFlags.
* @param parameters The parameters of the method. Partial matches allowed and follow the same rules as returnType.
* @param opcodes An opcode pattern of the method's instructions. Wildcard or unknown opcodes can be specified by null.
* @param strings A list of the method's strings compared each using String.contains.
* @param reference A supplier for the method reference name value to check for.
*/
abstract class MethodReferenceNameFingerprint(
returnType: String? = null,
accessFlags: Int? = null,
parameters: Iterable<String>? = null,
opcodes: Iterable<Opcode>? = null,
strings: Iterable<String>? = null,
// Has to be a supplier because the fingerprint is created before patches can check reference.
reference: () -> String
) : MethodFingerprint(
returnType = returnType,
accessFlags = accessFlags,
parameters = parameters,
opcodes = opcodes,
strings = strings,
customFingerprint = { methodDef, _ ->
methodDef.containsMethodReferenceNameInstructionIndex(reference())
}
)