fix: remove OneUI unlocked icon cap
This commit is contained in:
+65
-1
@@ -4,6 +4,8 @@ import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import io.github.libxposed.api.XposedInterface
|
||||
import se.ajpanton.notificationsmaster.visibility.NotificationSurface
|
||||
import java.lang.reflect.Method
|
||||
@@ -14,7 +16,9 @@ import java.util.function.Function
|
||||
/** Filters only OneUI's native unlocked status-bar container. */
|
||||
internal class OneUiUnlockedIconBackend(private val framework: XposedInterface) : VisibilitySurfaceBackend {
|
||||
private val controllers = Collections.newSetFromMap(WeakHashMap<Any, Boolean>())
|
||||
private val iconContainers = Collections.newSetFromMap(WeakHashMap<View, Boolean>())
|
||||
private lateinit var updateStatusBarIcons: Method
|
||||
private lateinit var maxStaticIcons: java.lang.reflect.Field
|
||||
@Volatile private var blockedObserved = false
|
||||
|
||||
override fun install(classLoader: ClassLoader): Boolean = runCatching {
|
||||
@@ -25,6 +29,10 @@ internal class OneUiUnlockedIconBackend(private val framework: XposedInterface)
|
||||
require(it.type == container)
|
||||
it.isAccessible = true
|
||||
}
|
||||
maxStaticIcons = container.getDeclaredField("mMaxStaticIcons").also {
|
||||
require(it.type == Int::class.javaPrimitiveType)
|
||||
it.isAccessible = true
|
||||
}
|
||||
val sbn = entry.getDeclaredField("mSbn").also {
|
||||
require(it.type == StatusBarNotification::class.java)
|
||||
it.isAccessible = true
|
||||
@@ -50,10 +58,13 @@ internal class OneUiUnlockedIconBackend(private val framework: XposedInterface)
|
||||
updateStatusBarIcons.isAccessible = true
|
||||
framework.hook(updateStatusBarIcons).intercept { chain ->
|
||||
synchronized(controllers) { controllers += chain.thisObject }
|
||||
(notificationIcons.get(chain.thisObject) as? View)?.let(::manage)
|
||||
chain.proceed()
|
||||
}
|
||||
framework.hook(update).intercept { chain ->
|
||||
if (chain.args[1] !== notificationIcons.get(chain.thisObject)) return@intercept chain.proceed()
|
||||
val icons = notificationIcons.get(chain.thisObject)
|
||||
if (chain.args[1] !== icons) return@intercept chain.proceed()
|
||||
(icons as? View)?.let(::manage)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val original = chain.args[0] as? Function<Any, Any?> ?: return@intercept chain.proceed()
|
||||
val wrapped = Function<Any, Any?> { item ->
|
||||
@@ -77,6 +88,28 @@ internal class OneUiUnlockedIconBackend(private val framework: XposedInterface)
|
||||
args[0] = wrapped
|
||||
chain.proceed(args)
|
||||
}
|
||||
container.declaredMethods.filter { it.name == "calculateIconXTranslations" }.forEach { method ->
|
||||
method.isAccessible = true
|
||||
framework.hook(method).intercept { chain ->
|
||||
(chain.thisObject as? View)?.takeIf(::isManaged)?.let(::applyLimit)
|
||||
chain.proceed()
|
||||
}
|
||||
}
|
||||
container.declaredMethods.filter { it.name == "shouldForceOverflow" }.forEach { method ->
|
||||
method.isAccessible = true
|
||||
framework.hook(method).intercept { chain ->
|
||||
val view = chain.thisObject as? View
|
||||
if (view == null || !isManaged(view) || chain.args.size < 4) {
|
||||
return@intercept chain.proceed()
|
||||
}
|
||||
val limit = unlockedLimit()
|
||||
applyLimit(view)
|
||||
val index = chain.args[0] as? Int ?: return@intercept chain.proceed()
|
||||
val speedBump = chain.args[1] as? Int ?: -1
|
||||
val appear = chain.args[2] as? Float ?: 0f
|
||||
(speedBump != -1 && index >= speedBump && appear > 0f) || index >= limit
|
||||
}
|
||||
}
|
||||
}.onSuccess {
|
||||
Log.i(TAG, "Installed OneUI unlocked notification-icon backend")
|
||||
}.onFailure {
|
||||
@@ -94,10 +127,41 @@ internal class OneUiUnlockedIconBackend(private val framework: XposedInterface)
|
||||
}
|
||||
}
|
||||
|
||||
private fun manage(view: View) {
|
||||
synchronized(iconContainers) { iconContainers += view }
|
||||
applyLimit(view)
|
||||
widenParent(view)
|
||||
}
|
||||
|
||||
private fun isManaged(view: View) = synchronized(iconContainers) { view in iconContainers }
|
||||
|
||||
private fun applyLimit(view: View) {
|
||||
maxStaticIcons.setInt(view, unlockedLimit())
|
||||
}
|
||||
|
||||
private fun unlockedLimit() = ProcessVisibilityPolicyCache.unlockedIconLimit ?: UNLIMITED_ICONS
|
||||
|
||||
private fun widenParent(view: View) {
|
||||
var parent = view.parent as? View
|
||||
repeat(3) {
|
||||
val current = parent ?: return
|
||||
if (current.javaClass.name.contains("AlphaOptimized")) {
|
||||
current.layoutParams?.takeIf {
|
||||
it.width == ViewGroup.LayoutParams.WRAP_CONTENT || it.width == 0
|
||||
}?.let {
|
||||
it.width = ViewGroup.LayoutParams.MATCH_PARENT
|
||||
current.layoutParams = it
|
||||
}
|
||||
}
|
||||
parent = current.parent as? View
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "NotificationsMaster"
|
||||
const val CONTROLLER = "com.android.systemui.statusbar.phone.LegacyNotificationIconAreaControllerImpl"
|
||||
const val ICON_CONTAINER = "com.android.systemui.statusbar.phone.NotificationIconContainer"
|
||||
const val NOTIFICATION_ENTRY = "com.android.systemui.statusbar.notification.collection.NotificationEntry"
|
||||
const val UNLIMITED_ICONS = 1000
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user