some more migrations
This commit is contained in:
parent
56eff2a625
commit
3a3fe5ed9b
15 changed files with 168 additions and 261 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
package app.revanced.patches.music.misc.gms
|
package app.revanced.patches.music.misc.gms
|
||||||
|
|
||||||
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.patch.Option
|
import app.revanced.patcher.patch.Option
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
import app.revanced.patches.all.misc.resources.addResources
|
||||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||||
|
|
@ -19,7 +20,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||||
fromPackageName = MUSIC_PACKAGE_NAME,
|
fromPackageName = MUSIC_PACKAGE_NAME,
|
||||||
toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
|
toPackageName = REVANCED_MUSIC_PACKAGE_NAME,
|
||||||
getPrimeMethod = { primeMethod },
|
getPrimeMethod = { primeMethod },
|
||||||
getEarlyReturnMethods = { setOf(castContextFetchMethod) },
|
earlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get),
|
||||||
getMainActivityOnCreateMethod = { musicActivityOnCreateMethod },
|
getMainActivityOnCreateMethod = { musicActivityOnCreateMethod },
|
||||||
extensionPatch = sharedExtensionPatch,
|
extensionPatch = sharedExtensionPatch,
|
||||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||||
|
|
@ -28,8 +29,8 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||||
compatibleWith(
|
compatibleWith(
|
||||||
MUSIC_PACKAGE_NAME(
|
MUSIC_PACKAGE_NAME(
|
||||||
"7.29.52",
|
"7.29.52",
|
||||||
"8.10.52"
|
"8.10.52",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,17 +51,17 @@ private fun gmsCoreSupportResourcePatch(
|
||||||
"microg_settings",
|
"microg_settings",
|
||||||
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
||||||
"$gmsCoreVendorGroupId.android.gms"
|
"$gmsCoreVendorGroupId.android.gms"
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
addResourcesPatch,
|
addResourcesPatch,
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
fileProviderPatch(
|
fileProviderPatch(
|
||||||
MUSIC_PACKAGE_NAME,
|
MUSIC_PACKAGE_NAME,
|
||||||
REVANCED_MUSIC_PACKAGE_NAME
|
REVANCED_MUSIC_PACKAGE_NAME,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -334,7 +334,7 @@ internal fun baseCustomBrandingPatch(
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bundled icons.
|
// Bundled icons.
|
||||||
iconStyleNames.forEachIndexed { index, style ->
|
iconStyleNames.forEach { style ->
|
||||||
application.appendChild(
|
application.appendChild(
|
||||||
createAlias(
|
createAlias(
|
||||||
aliasName = aliasName(style),
|
aliasName = aliasName(style),
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
package app.revanced.patches.shared.layout.branding
|
package app.revanced.patches.shared.layout.branding
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.numberOfPresetAppNamesExtensionMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("numberOfPresetAppNames")
|
||||||
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("I")
|
returnType("I")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "numberOfPresetAppNames" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A much simpler fingerprint exists that can set the small icon (contains string "414843287017"),
|
// A much simpler fingerprint exists that can set the small icon (contains string "414843287017"),
|
||||||
// but that has limited usage and this fingerprint allows changing any part of the notification.
|
// but that has limited usage and this fingerprint allows changing any part of the notification.
|
||||||
internal val BytecodePatchContext.notificationMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.notificationMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
|
"key_action_priority",
|
||||||
|
) {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.CONSTRUCTOR)
|
||||||
parameterTypes("L")
|
parameterTypes("L")
|
||||||
strings("key_action_priority")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,10 @@
|
||||||
package app.revanced.patches.shared.misc.gms
|
package app.revanced.patches.shared.misc.gms
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
|
|
||||||
internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodDeclaratively(
|
internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMutableMethodDeclarativelyOrNull(
|
||||||
"This should never happen.",
|
"This should never happen.",
|
||||||
"MetadataValueReader",
|
"MetadataValueReader",
|
||||||
"com.google.android.gms",
|
"com.google.android.gms",
|
||||||
|
|
@ -17,7 +14,7 @@ internal val BytecodePatchContext.googlePlayUtilityMethod by gettingFirstMethodD
|
||||||
parameterTypes("L", "I")
|
parameterTypes("L", "I")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclaratively(
|
internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMutableMethodDeclaratively(
|
||||||
"Google Play Services not available",
|
"Google Play Services not available",
|
||||||
) {
|
) {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.STATIC)
|
||||||
|
|
@ -25,20 +22,18 @@ internal val BytecodePatchContext.serviceCheckMethod by gettingFirstMethodDeclar
|
||||||
parameterTypes("L", "I")
|
parameterTypes("L", "I")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.gmsCoreSupportMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("getGmsCoreVendorGroupId")
|
||||||
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("Ljava/lang/String;")
|
returnType("Ljava/lang/String;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "getGmsCoreVendorGroupId" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.originalPackageNameExtensionMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.originalPackageNameExtensionMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("getOriginalPackageName")
|
||||||
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("Ljava/lang/String;")
|
returnType("Ljava/lang/String;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
custom { methodDef, classDef ->
|
|
||||||
methodDef.name == "getOriginalPackageName" && classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import app.revanced.patcher.extensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.instructions
|
import app.revanced.patcher.extensions.instructions
|
||||||
import app.revanced.patcher.extensions.replaceInstruction
|
import app.revanced.patcher.extensions.replaceInstruction
|
||||||
import app.revanced.patcher.patch.*
|
import app.revanced.patcher.patch.*
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
|
||||||
import app.revanced.patches.all.misc.packagename.`Change package name`
|
import app.revanced.patches.all.misc.packagename.`Change package name`
|
||||||
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
import app.revanced.patches.all.misc.packagename.setOrGetFallbackPackageName
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
import app.revanced.patches.all.misc.resources.addResources
|
||||||
|
|
@ -36,7 +35,7 @@ private const val PACKAGE_NAME_REGEX_PATTERN = "^[a-z]\\w*(\\.[a-z]\\w*)+\$"
|
||||||
* @param fromPackageName The package name of the original app.
|
* @param fromPackageName The package name of the original app.
|
||||||
* @param toPackageName The package name to fall back to if no custom package name is specified in patch options.
|
* @param toPackageName The package name to fall back to if no custom package name is specified in patch options.
|
||||||
* @param getPrimeMethod The "prime" method that needs to be patched.
|
* @param getPrimeMethod The "prime" method that needs to be patched.
|
||||||
* @param getEarlyReturnMethods The methods that need to be returned early.
|
* @param earlyReturnMethods The methods that need to be returned early.
|
||||||
* @param getMainActivityOnCreateMethod The main activity onCreate method.
|
* @param getMainActivityOnCreateMethod The main activity onCreate method.
|
||||||
* @param extensionPatch The patch responsible for the extension.
|
* @param extensionPatch The patch responsible for the extension.
|
||||||
* @param gmsCoreSupportResourcePatchFactory The factory for the corresponding resource patch
|
* @param gmsCoreSupportResourcePatchFactory The factory for the corresponding resource patch
|
||||||
|
|
@ -48,7 +47,7 @@ fun gmsCoreSupportPatch(
|
||||||
fromPackageName: String,
|
fromPackageName: String,
|
||||||
toPackageName: String,
|
toPackageName: String,
|
||||||
getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null,
|
getPrimeMethod: (BytecodePatchContext.() -> MutableMethod)? = null,
|
||||||
getEarlyReturnMethods: Set<BytecodePatchContext.() -> MutableMethod> = emptySet(),
|
earlyReturnMethods: Set<BytecodePatchContext.() -> MutableMethod> = emptySet(),
|
||||||
getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
|
getMainActivityOnCreateMethod: BytecodePatchContext.() -> MutableMethod,
|
||||||
extensionPatch: Patch,
|
extensionPatch: Patch,
|
||||||
gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option<String>) -> Patch,
|
gmsCoreSupportResourcePatchFactory: (gmsCoreVendorGroupIdOption: Option<String>) -> Patch,
|
||||||
|
|
@ -203,13 +202,11 @@ fun gmsCoreSupportPatch(
|
||||||
getPrimeMethod?.let { transformPrimeMethod(packageName) }
|
getPrimeMethod?.let { transformPrimeMethod(packageName) }
|
||||||
|
|
||||||
// Return these methods early to prevent the app from crashing.
|
// Return these methods early to prevent the app from crashing.
|
||||||
getEarlyReturnMethods().forEach { it.returnEarly() }
|
earlyReturnMethods.forEach { it().returnEarly() }
|
||||||
serviceCheckMethod.returnEarly()
|
serviceCheckMethod.returnEarly()
|
||||||
|
|
||||||
// Google Play Utility is not present in all apps, so we need to check if it's present.
|
// Google Play Utility is not present in all apps, so we need to check if it's present.
|
||||||
if (googlePlayUtilityMethodOrNull != null) {
|
googlePlayUtilityMethod?.returnEarly(0)
|
||||||
googlePlayUtilityMethod.returnEarly(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set original and patched package names for extension to use.
|
// Set original and patched package names for extension to use.
|
||||||
originalPackageNameExtensionMethod.returnEarly(fromPackageName)
|
originalPackageNameExtensionMethod.returnEarly(fromPackageName)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||||
fromPackageName = YOUTUBE_PACKAGE_NAME,
|
fromPackageName = YOUTUBE_PACKAGE_NAME,
|
||||||
toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME,
|
toPackageName = REVANCED_YOUTUBE_PACKAGE_NAME,
|
||||||
getPrimeMethod = BytecodePatchContext::primeMethod::get,
|
getPrimeMethod = BytecodePatchContext::primeMethod::get,
|
||||||
getEarlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get),
|
earlyReturnMethods = setOf(BytecodePatchContext::castContextFetchMethod::get),
|
||||||
getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get,
|
getMainActivityOnCreateMethod = BytecodePatchContext::mainActivityOnCreateMethod::get,
|
||||||
extensionPatch = sharedExtensionPatch,
|
extensionPatch = sharedExtensionPatch,
|
||||||
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
gmsCoreSupportResourcePatchFactory = ::gmsCoreSupportResourcePatch,
|
||||||
|
|
@ -38,7 +38,7 @@ val gmsCoreSupportPatch = gmsCoreSupportPatch(
|
||||||
"20.14.43",
|
"20.14.43",
|
||||||
"20.21.37",
|
"20.21.37",
|
||||||
"20.31.40",
|
"20.31.40",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,14 +59,14 @@ private fun gmsCoreSupportResourcePatch(
|
||||||
"microg_settings",
|
"microg_settings",
|
||||||
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
intent = IntentPreference.Intent("", "org.microg.gms.ui.SettingsActivity") {
|
||||||
"$gmsCoreVendorGroupId.android.gms"
|
"$gmsCoreVendorGroupId.android.gms"
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
dependsOn(
|
dependsOn(
|
||||||
addResourcesPatch,
|
addResourcesPatch,
|
||||||
settingsPatch,
|
settingsPatch,
|
||||||
accountCredentialsInvalidTextPatch
|
accountCredentialsInvalidTextPatch,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,14 @@
|
||||||
package app.revanced.patches.youtube.misc.playercontrols
|
package app.revanced.patches.youtube.misc.playercontrols
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.checkCast
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.methodCall
|
|
||||||
import app.revanced.patcher.opcode
|
|
||||||
import app.revanced.patcher.opcodes
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
import com.android.tools.smali.dexlib2.iface.ClassDef
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsVisibilityEntityModelMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsVisibilityEntityModelMethod by gettingFirstMethodDeclaratively {
|
||||||
|
name("getPlayerControlsVisibility")
|
||||||
accessFlags(AccessFlags.PUBLIC)
|
accessFlags(AccessFlags.PUBLIC)
|
||||||
returnType("L")
|
returnType("L")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
|
|
@ -23,131 +16,113 @@ internal val BytecodePatchContext.playerControlsVisibilityEntityModelMethod by g
|
||||||
Opcode.IGET,
|
Opcode.IGET,
|
||||||
Opcode.INVOKE_STATIC,
|
Opcode.INVOKE_STATIC,
|
||||||
)
|
)
|
||||||
custom { method, _ ->
|
|
||||||
method.name == "getPlayerControlsVisibility"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.youtubeControlsOverlayMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.youtubeControlsOverlayMethod by gettingFirstMethodDeclaratively {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(
|
||||||
methodCall(name = "setFocusableInTouchMode"),
|
method("setFocusableInTouchMode"),
|
||||||
ResourceType.ID("inset_overlay_view_layout"),
|
ResourceType.ID("inset_overlay_view_layout"),
|
||||||
ResourceType.ID("scrim_overlay"),
|
ResourceType.ID("scrim_overlay"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.motionEventMethod by gettingFirstMethodDeclaratively {
|
internal val motionEventMethodMatch = firstMethodComposite {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Landroid/view/MotionEvent;")
|
parameterTypes("Landroid/view/MotionEvent;")
|
||||||
instructions(
|
instructions(method("setTranslationY"))
|
||||||
methodCall(name = "setTranslationY"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsExtensionHookListenersExistMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsExtensionHookListenersExistMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("fullscreenButtonVisibilityCallbacksExist")
|
||||||
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
custom { methodDef, classDef ->
|
|
||||||
methodDef.name == "fullscreenButtonVisibilityCallbacksExist" &&
|
|
||||||
classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsExtensionHookMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsExtensionHookMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("fullscreenButtonVisibilityChanged")
|
||||||
|
definingClass(EXTENSION_CLASS_DESCRIPTOR)
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.STATIC)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Z")
|
parameterTypes("Z")
|
||||||
custom { methodDef, classDef ->
|
|
||||||
methodDef.name == "fullscreenButtonVisibilityChanged" &&
|
|
||||||
classDef.type == EXTENSION_CLASS_DESCRIPTOR
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerTopControlsInflateMethod by gettingFirstMethodDeclaratively {
|
internal val playerTopControlsInflateMethod = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(
|
||||||
ResourceType.ID("controls_layout_stub"),
|
ResourceType.ID("controls_layout_stub"),
|
||||||
methodCall("Landroid/view/ViewStub;", "inflate"),
|
method { name == "inflate" && definingClass == "Landroid/view/ViewStub;" },
|
||||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
after(Opcode.MOVE_RESULT_OBJECT()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerBottomControlsInflateMethod by gettingFirstMethodDeclaratively {
|
internal val playerBottomControlsInflateMethodMatch = firstMethodComposite {
|
||||||
returnType("Ljava/lang/Object;")
|
returnType("Ljava/lang/Object;")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(
|
||||||
ResourceType.ID("bottom_ui_container_stub"),
|
ResourceType.ID("bottom_ui_container_stub"),
|
||||||
methodCall("Landroid/view/ViewStub;", "inflate"),
|
method { name == "inflate" && definingClass == "Landroid/view/ViewStub;" },
|
||||||
after(Opcode.MOVE_RESULT_OBJECT()),
|
after(Opcode.MOVE_RESULT_OBJECT()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.overlayViewInflateMethod by gettingFirstMethodDeclaratively {
|
internal val overlayViewInflateMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Landroid/view/View;")
|
parameterTypes("Landroid/view/View;")
|
||||||
instructions(
|
instructions(
|
||||||
ResourceType.ID("heatseeker_viewstub"),
|
ResourceType.ID("heatseeker_viewstub"),
|
||||||
ResourceType.ID("fullscreen_button"),
|
ResourceType.ID("fullscreen_button"),
|
||||||
checkCast("Landroid/widget/ImageView;"),
|
allOf(Opcode.CHECK_CAST(), type("Landroid/widget/ImageView;")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves to the class found in [playerTopControlsInflateMethod].
|
* Resolves to the class found in [playerTopControlsInflateMethod].
|
||||||
*/
|
*/
|
||||||
internal val BytecodePatchContext.controlsOverlayVisibilityMethod by gettingFirstMethodDeclaratively {
|
context(_: BytecodePatchContext)
|
||||||
|
internal fun ClassDef.getControlsOverlayVisibilityMethod() = firstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PRIVATE, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Z", "Z")
|
parameterTypes("Z", "Z")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerBottomControlsExploderFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerBottomControlsExploderFeatureFlagMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(45643739L())
|
||||||
45643739L(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerTopControlsExperimentalLayoutFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerTopControlsExperimentalLayoutFeatureFlagMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("I")
|
returnType("I")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(45629424L())
|
||||||
45629424L(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsLargeOverlayButtonsFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsLargeOverlayButtonsFeatureFlagMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(45709810L())
|
||||||
45709810L(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsFullscreenLargeButtonsFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsFullscreenLargeButtonsFeatureFlagMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(45686474L())
|
||||||
45686474L(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerControlsButtonStrokeFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerControlsButtonStrokeFeatureFlagMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(45713296L())
|
||||||
45713296L(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,15 @@ package app.revanced.patches.youtube.misc.playercontrols
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.addInstruction
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
|
import app.revanced.patcher.immutableClassDef
|
||||||
import app.revanced.patcher.patch.PatchException
|
import app.revanced.patcher.patch.PatchException
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patcher.patch.resourcePatch
|
import app.revanced.patcher.patch.resourcePatch
|
||||||
import app.revanced.patcher.util.Document
|
import app.revanced.patcher.util.Document
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||||
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
import app.revanced.patches.youtube.misc.extension.sharedExtensionPatch
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_25_or_greater
|
import app.revanced.patches.youtube.misc.playservice.*
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_19_35_or_greater
|
import app.revanced.util.*
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_20_19_or_greater
|
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_20_20_or_greater
|
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_20_28_or_greater
|
|
||||||
import app.revanced.patches.youtube.misc.playservice.is_20_30_or_greater
|
|
||||||
import app.revanced.patches.youtube.misc.playservice.versionCheckPatch
|
|
||||||
import app.revanced.util.copyXmlNode
|
|
||||||
import app.revanced.util.findElementByAttributeValue
|
|
||||||
import app.revanced.util.findElementByAttributeValueOrThrow
|
|
||||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
|
||||||
import app.revanced.util.inputStreamFromBundledResource
|
|
||||||
import app.revanced.util.returnEarly
|
|
||||||
import app.revanced.util.returnLate
|
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
|
||||||
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
import com.android.tools.smali.dexlib2.mutable.MutableMethod
|
||||||
|
|
@ -244,51 +233,44 @@ val playerControlsPatch = bytecodePatch(
|
||||||
)
|
)
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
playerBottomControlsInflateMethod.let {
|
playerBottomControlsInflateMethodMatch.method.apply {
|
||||||
it.method.apply {
|
inflateBottomControlMethod = this
|
||||||
inflateBottomControlMethod = this
|
|
||||||
|
|
||||||
val inflateReturnObjectIndex = it.indices.last()
|
val inflateReturnObjectIndex = playerBottomControlsInflateMethodMatch.indices.last()
|
||||||
inflateBottomControlRegister = getInstruction<OneRegisterInstruction>(inflateReturnObjectIndex).registerA
|
inflateBottomControlRegister = getInstruction<OneRegisterInstruction>(inflateReturnObjectIndex).registerA
|
||||||
inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1
|
inflateBottomControlInsertIndex = inflateReturnObjectIndex + 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
playerTopControlsInflateMethod.let {
|
playerTopControlsInflateMethod.method.apply {
|
||||||
it.method.apply {
|
inflateTopControlMethod = this
|
||||||
inflateTopControlMethod = this
|
|
||||||
|
|
||||||
val inflateReturnObjectIndex = it.indices.last()
|
val inflateReturnObjectIndex = playerTopControlsInflateMethod.indices.last()
|
||||||
inflateTopControlRegister = getInstruction<OneRegisterInstruction>(inflateReturnObjectIndex).registerA
|
inflateTopControlRegister = getInstruction<OneRegisterInstruction>(inflateReturnObjectIndex).registerA
|
||||||
inflateTopControlInsertIndex = inflateReturnObjectIndex + 1
|
inflateTopControlInsertIndex = inflateReturnObjectIndex + 1
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visibilityMethod = controlsOverlayVisibilityMethod.match(
|
visibilityMethod =
|
||||||
playerTopControlsInflateMethod.originalClassDef,
|
playerTopControlsInflateMethod.immutableClassDef.getControlsOverlayVisibilityMethod()
|
||||||
).method
|
|
||||||
|
|
||||||
// Hook the fullscreen close button. Used to fix visibility
|
// Hook the fullscreen close button. Used to fix visibility
|
||||||
// when seeking and other situations.
|
// when seeking and other situations.
|
||||||
overlayViewInflateMethod.let {
|
overlayViewInflateMethodMatch.method.apply {
|
||||||
it.method.apply {
|
val index = overlayViewInflateMethodMatch.indices.last()
|
||||||
val index = it.indices.last()
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
|
||||||
|
|
||||||
addInstruction(
|
addInstruction(
|
||||||
index + 1,
|
index + 1,
|
||||||
"invoke-static { v$register }, " +
|
"invoke-static { v$register }, " +
|
||||||
"$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V",
|
"$EXTENSION_CLASS_DESCRIPTOR->setFullscreenCloseButton(Landroid/widget/ImageView;)V",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistMethod
|
visibilityImmediateCallbacksExistMethod = playerControlsExtensionHookListenersExistMethod
|
||||||
visibilityImmediateMethod = playerControlsExtensionHookMethod
|
visibilityImmediateMethod = playerControlsExtensionHookMethod
|
||||||
|
|
||||||
motionEventMethod.match(youtubeControlsOverlayMethod.originalClassDef).let {
|
motionEventMethodMatch.match(youtubeControlsOverlayMethod.immutableClassDef).let {
|
||||||
visibilityNegatedImmediateMethod = it.method
|
visibilityNegatedImmediateMethod = it.method
|
||||||
visibilityNegatedImmediateInsertIndex = it.instructionMatches.first().index + 1
|
visibilityNegatedImmediateInsertIndex = it.indices.first() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// A/B test for a slightly different bottom overlay controls,
|
// A/B test for a slightly different bottom overlay controls,
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,28 @@
|
||||||
package app.revanced.patches.youtube.misc.playertype
|
package app.revanced.patches.youtube.misc.playertype
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.after
|
|
||||||
import app.revanced.patcher.afterAtMost
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.playerTypeEnumMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.playerTypeEnumMethod by gettingFirstMethodDeclaratively(
|
||||||
|
"NONE",
|
||||||
|
"HIDDEN",
|
||||||
|
"WATCH_WHILE_MINIMIZED",
|
||||||
|
"WATCH_WHILE_MAXIMIZED",
|
||||||
|
"WATCH_WHILE_FULLSCREEN",
|
||||||
|
"WATCH_WHILE_SLIDING_MAXIMIZED_FULLSCREEN",
|
||||||
|
"WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED",
|
||||||
|
"WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED",
|
||||||
|
"INLINE_MINIMAL",
|
||||||
|
"VIRTUAL_REALITY_FULLSCREEN",
|
||||||
|
"WATCH_WHILE_PICTURE_IN_PICTURE",
|
||||||
|
) {
|
||||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||||
strings(
|
|
||||||
"NONE",
|
|
||||||
"HIDDEN",
|
|
||||||
"WATCH_WHILE_MINIMIZED",
|
|
||||||
"WATCH_WHILE_MAXIMIZED",
|
|
||||||
"WATCH_WHILE_FULLSCREEN",
|
|
||||||
"WATCH_WHILE_SLIDING_MAXIMIZED_FULLSCREEN",
|
|
||||||
"WATCH_WHILE_SLIDING_MINIMIZED_MAXIMIZED",
|
|
||||||
"WATCH_WHILE_SLIDING_MINIMIZED_DISMISSED",
|
|
||||||
"INLINE_MINIMAL",
|
|
||||||
"VIRTUAL_REALITY_FULLSCREEN",
|
|
||||||
"WATCH_WHILE_PICTURE_IN_PICTURE",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.reelWatchPagerMethod by gettingFirstMethodDeclaratively {
|
internal val reelWatchPagerMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Landroid/view/View;")
|
returnType("Landroid/view/View;")
|
||||||
instructions(
|
instructions(
|
||||||
|
|
@ -39,17 +31,16 @@ internal val BytecodePatchContext.reelWatchPagerMethod by gettingFirstMethodDecl
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoStateEnumMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.videoStateEnumMethod by gettingFirstMethodDeclaratively(
|
||||||
|
"NEW",
|
||||||
|
"PLAYING",
|
||||||
|
"PAUSED",
|
||||||
|
"RECOVERABLE_ERROR",
|
||||||
|
"UNRECOVERABLE_ERROR",
|
||||||
|
"ENDED",
|
||||||
|
) {
|
||||||
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
accessFlags(AccessFlags.STATIC, AccessFlags.CONSTRUCTOR)
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
strings(
|
|
||||||
"NEW",
|
|
||||||
"PLAYING",
|
|
||||||
"PAUSED",
|
|
||||||
"RECOVERABLE_ERROR",
|
|
||||||
"UNRECOVERABLE_ERROR",
|
|
||||||
"ENDED",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 20.33 and lower class name ControlsState. 20.34+ class name is obfuscated.
|
// 20.33 and lower class name ControlsState. 20.34+ class name is obfuscated.
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package app.revanced.patches.youtube.misc.playertype
|
package app.revanced.patches.youtube.misc.playertype
|
||||||
|
|
||||||
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.extensions.addInstruction
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
import app.revanced.patcher.fieldAccess
|
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||||
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
import app.revanced.patches.shared.misc.mapping.resourceMappingPatch
|
||||||
|
|
@ -20,54 +20,44 @@ val playerTypeHookPatch = bytecodePatch(
|
||||||
dependsOn(sharedExtensionPatch, resourceMappingPatch)
|
dependsOn(sharedExtensionPatch, resourceMappingPatch)
|
||||||
|
|
||||||
apply {
|
apply {
|
||||||
val playerOverlaysSetPlayerTypeFingerprint = fingerprint {
|
firstMutableMethodDeclaratively {
|
||||||
|
definingClass { endsWith("/YouTubePlayerOverlaysLayout;") }
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes(playerTypeEnumMethod.originalClassDef.type)
|
parameterTypes(playerTypeEnumMethod.immutableClassDef.type)
|
||||||
custom { _, classDef ->
|
}.addInstruction(
|
||||||
classDef.endsWith("/YouTubePlayerOverlaysLayout;")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
playerOverlaysSetPlayerTypeFingerprint.method.addInstruction(
|
|
||||||
0,
|
0,
|
||||||
"invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V",
|
"invoke-static { p1 }, $EXTENSION_CLASS_DESCRIPTOR->setPlayerType(Ljava/lang/Enum;)V",
|
||||||
)
|
)
|
||||||
|
|
||||||
reelWatchPagerMethod.let {
|
reelWatchPagerMethodMatch.method.apply {
|
||||||
it.method.apply {
|
val index = reelWatchPagerMethodMatch.indices.last()
|
||||||
val index = it.indices.last()
|
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
||||||
val register = getInstruction<OneRegisterInstruction>(index).registerA
|
|
||||||
|
|
||||||
addInstruction(
|
addInstruction(
|
||||||
index + 1,
|
index + 1,
|
||||||
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V",
|
"invoke-static { v$register }, $EXTENSION_CLASS_DESCRIPTOR->onShortsCreate(Landroid/view/View;)V",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val controlStateType = controlsStateToStringMethod.originalClassDef.type
|
val controlStateType = controlsStateToStringMethod.immutableClassDef.type
|
||||||
|
|
||||||
val videoStateFingerprint = fingerprint {
|
val videoStateEnumMethod = videoStateEnumMethod
|
||||||
|
firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes(controlStateType)
|
parameterTypes(controlStateType)
|
||||||
instructions(
|
instructions(
|
||||||
|
field {
|
||||||
|
definingClass == controlStateType && type == videoStateEnumMethod.immutableClassDef.type
|
||||||
|
},
|
||||||
// Obfuscated parameter field name.
|
// Obfuscated parameter field name.
|
||||||
fieldAccess(
|
|
||||||
definingClass = controlStateType,
|
|
||||||
type = videoStateEnumMethod.originalClassDef.type,
|
|
||||||
),
|
|
||||||
ResourceType.STRING("accessibility_play"),
|
ResourceType.STRING("accessibility_play"),
|
||||||
ResourceType.STRING("accessibility_pause"),
|
ResourceType.STRING("accessibility_pause"),
|
||||||
)
|
)
|
||||||
}
|
}.let {
|
||||||
|
|
||||||
videoStateFingerprint.let {
|
|
||||||
it.method.apply {
|
it.method.apply {
|
||||||
val videoStateFieldName = getInstruction<ReferenceInstruction>(
|
val videoStateFieldName = getInstruction<ReferenceInstruction>(it.indices.first()).reference
|
||||||
it.instructionMatches.first().index,
|
|
||||||
).reference
|
|
||||||
|
|
||||||
addInstructions(
|
addInstructions(
|
||||||
0,
|
0,
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,38 @@
|
||||||
package app.revanced.patches.youtube.misc.settings
|
package app.revanced.patches.youtube.misc.settings
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.*
|
||||||
import app.revanced.patcher.after
|
|
||||||
import app.revanced.patcher.afterAtMost
|
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
|
||||||
import app.revanced.patcher.instructions
|
|
||||||
import app.revanced.patcher.invoke
|
|
||||||
import app.revanced.patcher.opcode
|
|
||||||
import app.revanced.patcher.parameterTypes
|
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
import app.revanced.patcher.returnType
|
|
||||||
import app.revanced.patches.shared.misc.mapping.ResourceType
|
import app.revanced.patches.shared.misc.mapping.ResourceType
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.licenseActivityOnCreateMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.licenseActivityOnCreateMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
|
name("onCreate")
|
||||||
|
definingClass("/LicenseActivity;")
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes("Landroid/os/Bundle;")
|
parameterTypes("Landroid/os/Bundle;")
|
||||||
custom { method, classDef ->
|
|
||||||
method.name == "onCreate" && classDef.endsWith("/LicenseActivity;")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.setThemeMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.setThemeMethod by gettingFirstMutableMethodDeclaratively {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("L")
|
returnType("L")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
instructions(
|
instructions(ResourceType.STRING("app_theme_appearance_dark"))
|
||||||
ResourceType.STRING("app_theme_appearance_dark"),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.cairoFragmentConfigMethod by gettingFirstMethodDeclaratively {
|
internal val cairoFragmentConfigMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
instructions(
|
instructions(
|
||||||
45532100L(),
|
45532100L(),
|
||||||
|
|
||||||
afterAtMost(10, Opcode.MOVE_RESULT()),
|
afterAtMost(10, Opcode.MOVE_RESULT()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flag is present in 20.23, but bold icons are missing and forcing them crashes the app.
|
// Flag is present in 20.23, but bold icons are missing and forcing them crashes the app.
|
||||||
// 20.31 is the first target with all the bold icons present.
|
// 20.31 is the first target with all the bold icons present.
|
||||||
internal val BytecodePatchContext.boldIconsFeatureFlagMethod by gettingFirstMethodDeclaratively {
|
internal val boldIconsFeatureFlagMethod = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("Z")
|
returnType("Z")
|
||||||
parameterTypes()
|
parameterTypes()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package app.revanced.patches.youtube.misc.settings
|
package app.revanced.patches.youtube.misc.settings
|
||||||
|
|
||||||
|
import app.revanced.patcher.classDef
|
||||||
import app.revanced.patcher.extensions.addInstructions
|
import app.revanced.patcher.extensions.addInstructions
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
|
|
@ -239,8 +240,8 @@ val settingsPatch = bytecodePatch(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add setting to force Cairo settings fragment on/off.
|
// Add setting to force Cairo settings fragment on/off.
|
||||||
cairoFragmentConfigMethod.insertLiteralOverride(
|
cairoFragmentConfigMethodMatch.method.insertLiteralOverride(
|
||||||
cairoFragmentConfigMethod.instructionMatches.first().index,
|
cairoFragmentConfigMethodMatch.indices.first(),
|
||||||
"$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z",
|
"$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useCairoSettingsFragment(Z)Z",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -249,7 +250,7 @@ val settingsPatch = bytecodePatch(
|
||||||
if (is_20_31_or_greater) {
|
if (is_20_31_or_greater) {
|
||||||
boldIconsFeatureFlagMethod.let {
|
boldIconsFeatureFlagMethod.let {
|
||||||
it.method.insertLiteralOverride(
|
it.method.insertLiteralOverride(
|
||||||
it.instructionMatches.first().index,
|
it.indices.first(),
|
||||||
"$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useBoldIcons(Z)Z",
|
"$YOUTUBE_ACTIVITY_HOOK_CLASS_DESCRIPTOR->useBoldIcons(Z)Z",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -47,20 +47,15 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Used for the old type of the video quality menu.
|
// Used for the old type of the video quality menu.
|
||||||
videoQualityBottomSheetListFragmentname = getResourceId(
|
videoQualityBottomSheetListFragmentname =
|
||||||
ResourceType.LAYOUT,
|
ResourceType.LAYOUT["video_quality_bottom_sheet_list_fragment_title"]
|
||||||
"video_quality_bottom_sheet_list_fragment_title",
|
videoQualityQuickMenuAdvancedMenuDescription =
|
||||||
)
|
ResourceType.STRING["video_quality_quick_menu_advanced_menu_description"]
|
||||||
|
|
||||||
videoQualityQuickMenuAdvancedMenuDescription = getResourceId(
|
|
||||||
ResourceType.STRING,
|
|
||||||
"video_quality_quick_menu_advanced_menu_description",
|
|
||||||
)
|
|
||||||
|
|
||||||
// region Patch for the old type of the video quality menu.
|
// region Patch for the old type of the video quality menu.
|
||||||
// Used for regular videos when spoofing to old app version,
|
// Used for regular videos when spoofing to old app version,
|
||||||
// and for the Shorts quality flyout on newer app versions.
|
// and for the Shorts quality flyout on newer app versions.
|
||||||
videoQualityMenuViewInflateMethod.let {
|
videoQualityMenuViewInflateMethodMatch.let {
|
||||||
it.method.apply {
|
it.method.apply {
|
||||||
val checkCastIndex = it.indices.last()
|
val checkCastIndex = it.indices.last()
|
||||||
val listViewRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
val listViewRegister = getInstruction<OneRegisterInstruction>(checkCastIndex).registerA
|
||||||
|
|
@ -74,10 +69,10 @@ internal val advancedVideoQualityMenuPatch = bytecodePatch {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force YT to add the 'advanced' quality menu for Shorts.
|
// Force YT to add the 'advanced' quality menu for Shorts.
|
||||||
videoQualityMenuOptionsMethod.let {
|
videoQualityMenuOptionsMethodMatch.let {
|
||||||
val patternMatch = it.instructionMatches
|
val startIndex = it.indices.first()
|
||||||
val startIndex = patternMatch.first().index
|
val insertIndex = it.indices.last()
|
||||||
val insertIndex = patternMatch.last().index
|
|
||||||
if (startIndex != 0) throw PatchException("Unexpected opcode start index: $startIndex")
|
if (startIndex != 0) throw PatchException("Unexpected opcode start index: $startIndex")
|
||||||
|
|
||||||
it.method.apply {
|
it.method.apply {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
package app.revanced.patches.youtube.video.quality
|
package app.revanced.patches.youtube.video.quality
|
||||||
|
|
||||||
import app.revanced.patcher.accessFlags
|
import app.revanced.patcher.accessFlags
|
||||||
import app.revanced.patcher.addString
|
import app.revanced.patcher.firstMethodComposite
|
||||||
|
import app.revanced.patcher.firstMutableMethodDeclaratively
|
||||||
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
import app.revanced.patcher.gettingFirstMethodDeclaratively
|
||||||
import app.revanced.patcher.instructions
|
import app.revanced.patcher.name
|
||||||
import app.revanced.patcher.opcodes
|
import app.revanced.patcher.opcodes
|
||||||
import app.revanced.patcher.parameterTypes
|
import app.revanced.patcher.parameterTypes
|
||||||
import app.revanced.patcher.patch.BytecodePatchContext
|
import app.revanced.patcher.patch.BytecodePatchContext
|
||||||
|
|
@ -12,17 +13,15 @@ import app.revanced.util.literal
|
||||||
import com.android.tools.smali.dexlib2.AccessFlags
|
import com.android.tools.smali.dexlib2.AccessFlags
|
||||||
import com.android.tools.smali.dexlib2.Opcode
|
import com.android.tools.smali.dexlib2.Opcode
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively {
|
internal val BytecodePatchContext.videoQualityItemOnClickParentMethod by gettingFirstMethodDeclaratively(
|
||||||
|
"VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT",
|
||||||
|
) {
|
||||||
returnType("V")
|
returnType("V")
|
||||||
instructions(
|
|
||||||
"VIDEO_QUALITIES_MENU_BOTTOM_SHEET_FRAGMENT"(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
context(_: BytecodePatchContext)
|
||||||
* Resolves to class found in [videoQualityItemOnClickMethod].
|
internal fun com.android.tools.smali.dexlib2.iface.ClassDef.getVideoQualityItemOnClickMethod() = firstMutableMethodDeclaratively {
|
||||||
*/
|
name("onItemClick")
|
||||||
internal val BytecodePatchContext.videoQualityItemOnClickMethod by gettingFirstMethodDeclaratively {
|
|
||||||
returnType("V")
|
returnType("V")
|
||||||
parameterTypes(
|
parameterTypes(
|
||||||
"Landroid/widget/AdapterView;",
|
"Landroid/widget/AdapterView;",
|
||||||
|
|
@ -30,12 +29,9 @@ internal val BytecodePatchContext.videoQualityItemOnClickMethod by gettingFirstM
|
||||||
"I",
|
"I",
|
||||||
"J",
|
"J",
|
||||||
)
|
)
|
||||||
custom { method, _ ->
|
|
||||||
method.name == "onItemClick"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoQualityMenuOptionsMethod by gettingFirstMethodDeclaratively {
|
internal val videoQualityMenuOptionsMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.STATIC)
|
accessFlags(AccessFlags.STATIC)
|
||||||
returnType("[L")
|
returnType("[L")
|
||||||
parameterTypes("Landroid/content/Context", "L", "L")
|
parameterTypes("Landroid/content/Context", "L", "L")
|
||||||
|
|
@ -49,7 +45,7 @@ internal val BytecodePatchContext.videoQualityMenuOptionsMethod by gettingFirstM
|
||||||
literal { videoQualityQuickMenuAdvancedMenuDescription }
|
literal { videoQualityQuickMenuAdvancedMenuDescription }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val BytecodePatchContext.videoQualityMenuViewInflateMethod by gettingFirstMethodDeclaratively {
|
internal val videoQualityMenuViewInflateMethodMatch = firstMethodComposite {
|
||||||
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
accessFlags(AccessFlags.PUBLIC, AccessFlags.FINAL)
|
||||||
returnType("L")
|
returnType("L")
|
||||||
parameterTypes("L", "L", "L")
|
parameterTypes("L", "L", "L")
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package app.revanced.patches.youtube.video.quality
|
||||||
|
|
||||||
import app.revanced.patcher.extensions.addInstruction
|
import app.revanced.patcher.extensions.addInstruction
|
||||||
import app.revanced.patcher.extensions.getInstruction
|
import app.revanced.patcher.extensions.getInstruction
|
||||||
|
import app.revanced.patcher.immutableClassDef
|
||||||
import app.revanced.patcher.patch.bytecodePatch
|
import app.revanced.patcher.patch.bytecodePatch
|
||||||
import app.revanced.patches.all.misc.resources.addResources
|
import app.revanced.patches.all.misc.resources.addResources
|
||||||
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
import app.revanced.patches.all.misc.resources.addResourcesPatch
|
||||||
|
|
@ -64,9 +65,7 @@ val rememberVideoQualityPatch = bytecodePatch {
|
||||||
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
|
onCreateHook(EXTENSION_CLASS_DESCRIPTOR, "newVideoStarted")
|
||||||
|
|
||||||
// Inject a call to remember the selected quality for Shorts.
|
// Inject a call to remember the selected quality for Shorts.
|
||||||
videoQualityItemOnClickMethod.match(
|
videoQualityItemOnClickParentMethod.immutableClassDef.getVideoQualityItemOnClickMethod().addInstruction(
|
||||||
videoQualityItemOnClickParentMethod.classDef,
|
|
||||||
).method.addInstruction(
|
|
||||||
0,
|
0,
|
||||||
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V",
|
"invoke-static { p3 }, $EXTENSION_CLASS_DESCRIPTOR->userChangedShortsQuality(I)V",
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue