Skip to content

hyperos2 A15失效 #5

@powerAn2020

Description

@powerAn2020

大佬,看了下代码,hook的代码没了,本身不是搞android开发的,所以照猫画虎改了点位,但是不好使,直接进系统了。。
附件是从mi14p hyperos2.0.101提取的

package com.gswxxn.notiface

import android.animation.AnimatorSet
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.drawable.Animatable
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Message
import android.util.Log
import androidx.annotation.OptIn
import androidx.media3.common.util.UnstableApi
import com.gswxxn.notiface.wrapper.AnimatedVectorDrawableCompatWrapper
import com.gswxxn.notiface.wrapper.MiuiKeyguardFaceUnlockViewWrapper
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XC_MethodReplacement
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import de.robv.android.xposed.callbacks.XC_LoadPackage


class NewSystemUIHookEntry(lpparam: XC_LoadPackage.LoadPackageParam) {

    var shadeListBuilderInstance: Any? = null

    private val mExpandableNotificationRow by lazy {
        XposedHelpers.findClass(
            "com.android.systemui.statusbar.notification.row.ExpandableNotificationRow",
            lpparam.classLoader
        )
    }

    private val mIHapticFeedBack by lazy {
        XposedHelpers.findClass("com.miui.interfaces.IHapticFeedBack", lpparam.classLoader)
    }

    private val mMiuiDependency by lazy {
        XposedHelpers.findClass("com.miui.systemui.MiuiDependency", lpparam.classLoader)
    }

    private val mIMiuiFaceUnlockManager by lazy {
        XposedHelpers.findClass(
            "com.miui.interfaces.keyguard.IMiuiFaceUnlockManager",
            lpparam.classLoader
        )
    }
    private val keyguardUpdateMonitor by lazy {
        XposedHelpers.findClass("com.android.keyguard.KeyguardUpdateMonitor", lpparam.classLoader)
    }
    private val systemUIDeviceEntryFaceAuthInteractor by lazy {
        XposedHelpers.findClass(
            "com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor",
            lpparam.classLoader
        )
    }

    var isFaceUnlocked = false

    init {

        // 获取 ShadeListBuilder 实例
        XposedHelpers.findAndHookMethod(
            "com.android.systemui.statusbar.notification.collection.ShadeListBuilder",
            lpparam.classLoader,
            "buildList",
            object : XC_MethodHook() {
                override fun beforeHookedMethod(param: MethodHookParam) {
                    if (!isFaceUnlocked)
                        shadeListBuilderInstance = param.thisObject
                }
            }
        )

        //A14版本
        var handleMessageInnerClassName = "com.android.keyguard.KeyguardUpdateMonitor$15"

        //A15版本
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.VANILLA_ICE_CREAM) {
            handleMessageInnerClassName = "com.android.keyguard.KeyguardUpdateMonitor$13"
        }
        // 获取当前锁屏状态
        XposedHelpers.findAndHookMethod(handleMessageInnerClassName,
            lpparam.classLoader,
            "handleMessage",
            Message::class.java,
            object : XC_MethodHook() {
                @OptIn(UnstableApi::class)
                @Throws(Throwable::class)
                override fun beforeHookedMethod(param: MethodHookParam) {
                    val what = (param.args[0] as Message).what
                    val isStartedGoingToSleep = what == 321

                    // 息屏后设置 isFaceUnlocked 为 false, 并刷新通知 list
                    if (isStartedGoingToSleep) {
                        isFaceUnlocked = false
                        refreshNotificationDisplay()
                    }
                }
            })

        // Hook 人脸解锁成功事件
        XposedHelpers.findAndHookMethod("com.android.keyguard.KeyguardUpdateMonitor",
            lpparam.classLoader,
            "onFaceAuthenticated",
            Int::class.javaPrimitiveType, Boolean::class.javaPrimitiveType,
            object : XC_MethodReplacement() {
                override fun replaceHookedMethod(param: MethodHookParam?): Any? {
                    isFaceUnlocked = true
                    XposedBridge.log("刷新通知")
                    refreshNotificationDisplay()
                    XposedBridge.log("添加震动")
//               TODO 代码变动,失效了,暂时先不管都去掉
                    // 添加震动
//                    XposedHelpers.callStaticMethod(mMiuiDependency, "get", mIHapticFeedBack)
//                        .let {
//                            XposedHelpers.callMethod(
//                                it,
//                                "extExtHapticFeedback",
//                                206,
//                                "mesh_light",
//                                -1,
//                                0
//                            )
//                        }
                    XposedBridge.log("播放解锁成功动画")
                    // 播放解锁成功动画
//                    XposedHelpers.callStaticMethod(mMiuiDependency, "get", mIMiuiFaceUnlockManager)
//                        .let { XposedHelpers.getObjectField(it, "mFaceViewList") as ArrayList<*> }
//                        .forEach { mFaceViewList ->
//                            XposedHelpers.callMethod(mFaceViewList, "get")
//                                ?.let {
//                                    startFaceUnlockSuccessAnimation(
//                                        MiuiKeyguardFaceUnlockViewWrapper(it), lpparam.classLoader
//                                    )
//                                }
//                        }

                    return null
                }
            })

        // 解锁后 设置所有通知为非敏感
        XposedHelpers.findAndHookMethod(mExpandableNotificationRow, "setSensitive",
            Boolean::class.javaPrimitiveType, Boolean::class.javaPrimitiveType,
            object : XC_MethodHook() {
                override fun beforeHookedMethod(param: MethodHookParam?) {
                    super.beforeHookedMethod(param)
                    if (isFaceUnlocked) param!!.args[0] = false
                }
            })
        // 如果已成功解锁通知, 则不再重新监听人脸事件
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.VANILLA_ICE_CREAM) {
            // hyperOS2 A15版本中 KeyguardUpdateMonitor删除了shouldListenForFace,
            // 根据安卓15_r2版本显示这个方法实际调用的 SystemUIDeviceEntryFaceAuthInteractor 的 canFaceAuthRun()
            XposedHelpers.findAndHookMethod(
                "com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor",
                lpparam.classLoader,
                "canFaceAuthRun",
                object : XC_MethodHook() {
                    override fun beforeHookedMethod(param: MethodHookParam) {
                        if (isFaceUnlocked) param.result = false
                    }
                }
            )
        } else {
            XposedHelpers.findAndHookMethod(
                "com.android.keyguard.KeyguardUpdateMonitor",
                lpparam.classLoader,
                "shouldListenForFace",
                object : XC_MethodHook() {
                    override fun beforeHookedMethod(param: MethodHookParam) {
                        if (isFaceUnlocked) param.result = false
                    }
                }
            )
        }

        // A15貌似没生效
        // 播放展开通知动画的标志
        XposedHelpers.findAndHookMethod(
            "com.android.systemui.statusbar.notification.DynamicPrivacyController",
            lpparam.classLoader,
            "isDynamicallyUnlocked",
            object : XC_MethodHook() {
                override fun beforeHookedMethod(param: MethodHookParam) {
                    if (isFaceUnlocked) param.result = true
                }
            })
    }

    /**
     * 刷新通知显示
     */
    private fun refreshNotificationDisplay() {
        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.VANILLA_ICE_CREAM) {
           // 返回类型从List变成了NamedListenerSet
            val mOnBeforeRenderListListeners = XposedHelpers.getObjectField(
                shadeListBuilderInstance,
                "mOnBeforeRenderListListeners"
            )
            val mReadOnlyNotifList = XposedHelpers.getObjectField(
                shadeListBuilderInstance,
                "mReadOnlyNotifList"
            ) as List<*>
            // 使用反射获取 NamedListenerSet 的 iterator 方法
            val iteratorMethod =
                mOnBeforeRenderListListeners.javaClass.getMethod("iterator")
            // 调用 iterator 方法获取迭代器
            val iterator =
                iteratorMethod.invoke(mOnBeforeRenderListListeners) as Iterator<*>
            while (iterator.hasNext()) {
                val listener = iterator.next();
                if (listener != null) {
                    XposedBridge.log(listener.javaClass.name)
                    XposedHelpers.callMethod(
                        listener,
                        "onBeforeRenderList$1",
                        mReadOnlyNotifList
                    )
                }
            }
        } else {
            val mOnBeforeRenderListListeners = XposedHelpers.getObjectField(
                shadeListBuilderInstance,
                "mOnBeforeRenderListListeners"
            ) as List<*>
            val mReadOnlyNotifList = XposedHelpers.getObjectField(
                shadeListBuilderInstance,
                "mReadOnlyNotifList"
            ) as List<*>
            mOnBeforeRenderListListeners.forEach {
                XposedHelpers.callMethod(
                    it,
                    "onBeforeRenderList",
                    mReadOnlyNotifList
                )
            }
        }
    }

    // 播放人脸解锁成功动画
    fun startFaceUnlockSuccessAnimation(
        miuiKeyguardFaceUnlockView: MiuiKeyguardFaceUnlockViewWrapper,
        classLoader: ClassLoader
    ) {

        val animatorSet: AnimatorSet? = miuiKeyguardFaceUnlockView.mFaceUnlockAnimation
        if (animatorSet != null && animatorSet.isRunning()) {
            miuiKeyguardFaceUnlockView.mFaceUnlockAnimation.cancel()
        }
        miuiKeyguardFaceUnlockView.mRingIV.setAlpha(0.0f)
        miuiKeyguardFaceUnlockView.mRingIV.rotationY = 0.0f
        miuiKeyguardFaceUnlockView.mRingIV.translationX = 0.0f
        miuiKeyguardFaceUnlockView.mFaceIV.rotationY = 0.0f
        miuiKeyguardFaceUnlockView.mFaceIV.translationX = 0.0f

        val context2: Context = miuiKeyguardFaceUnlockView.getContext()
        val i =
            if (!miuiKeyguardFaceUnlockView.isPrimaryBouncerIsOrWillBeShowing() && miuiKeyguardFaceUnlockView.mLightLockWallpaper) {
                context2.getID("drawable", "face_unlock_black_success_ani")
            } else {
                context2.getID("drawable", "face_unlock_success_ani")
            }
        val animatedVectorDrawableCompat =
            AnimatedVectorDrawableCompatWrapper.newInstance(context2, classLoader)
        val resources = context2.resources
        val theme = context2.theme
        val drawable = resources.getDrawable(i, theme)
        drawable.callback = animatedVectorDrawableCompat.mCallback
        animatedVectorDrawableCompat.mDelegateDrawable = drawable
        miuiKeyguardFaceUnlockView.mSuccessfulAnimation =
            animatedVectorDrawableCompat.instance as Animatable
        animatedVectorDrawableCompat.registerAnimationCallback(miuiKeyguardFaceUnlockView.mSuccessAnimationListener)
        miuiKeyguardFaceUnlockView.mFaceIV.setImageDrawable(miuiKeyguardFaceUnlockView.mSuccessfulAnimation as Drawable)
        miuiKeyguardFaceUnlockView.mSuccessfulAnimation.start()
        miuiKeyguardFaceUnlockView.setContentDescription(
            miuiKeyguardFaceUnlockView.mContext.resources
                .getString(context2.getID("string", "face_unlock_success"))
        )
    }

    @SuppressLint("DiscouragedApi")
    private fun Context.getID(type: String, name: String): Int =
        resources.getIdentifier(name, type, "com.android.systemui")
}

MiuiSystemUI.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions