|
19 | 19 | package com.sevtinge.hyperceiler.libhook.rules.systemframework.display |
20 | 20 |
|
21 | 21 | import com.sevtinge.hyperceiler.libhook.base.BaseHook |
| 22 | +import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.getStaticObjectField |
22 | 23 | import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.hookAllMethods |
| 24 | +import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.hookMethod |
| 25 | +import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.getObjectField |
| 26 | +import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.setObjectField |
23 | 27 |
|
24 | 28 | object DisplayCutout : BaseHook() { |
25 | 29 | override fun init() { |
26 | | - findClass("android.view.DisplayCutout") |
| 30 | + val displayCutoutClass = findClass("android.view.DisplayCutout") |
| 31 | + val noCutout = displayCutoutClass.getStaticObjectField("NO_CUTOUT") |
| 32 | + |
| 33 | + displayCutoutClass |
27 | 34 | .hookAllMethods("pathAndDisplayCutoutFromSpec") { |
28 | 35 | before { |
29 | 36 | it.args[0] = "M 0,0 H 0 V 0 Z" |
30 | | - it.args[1] = "" |
| 37 | + // Android 16 prioritizes rectSpec when it is present. |
| 38 | + // An empty string causes the framework to return NULL_PAIR, |
| 39 | + // which propagates a null DisplayCutout to secondary displays. |
| 40 | + // Use null so the synthetic empty pathSpec remains effective. |
| 41 | + it.args[1] = null |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + listOf("fromResourcesRectApproximation", "fromSpec").forEach { methodName -> |
| 46 | + displayCutoutClass.hookAllMethods(methodName) { |
| 47 | + after { |
| 48 | + if (it.result == null) { |
| 49 | + it.result = noCutout |
| 50 | + } |
31 | 51 | } |
32 | 52 | } |
| 53 | + } |
| 54 | + |
| 55 | + val logicalDisplayClass = findClass("com.android.server.display.LogicalDisplay") |
| 56 | + logicalDisplayClass.hookMethod("getDisplayInfoLocked") { |
| 57 | + after { |
| 58 | + ensureNonNullDisplayCutout(it.result, noCutout) |
| 59 | + } |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + private fun ensureNonNullDisplayCutout(displayInfo: Any?, noCutout: Any?) { |
| 64 | + if (displayInfo == null || noCutout == null) return |
| 65 | + if (displayInfo.getObjectField("displayCutout") == null) { |
| 66 | + displayInfo.setObjectField("displayCutout", noCutout) |
| 67 | + } |
33 | 68 | } |
34 | 69 | } |
0 commit comments