Skip to content

hyperos2 A15失效 #5

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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