Add initial AOSP statusbar compatibility

This commit is contained in:
ajp_anton
2026-07-01 12:52:44 +00:00
parent 861ffd52d5
commit 42449f8c6a
5 changed files with 93 additions and 32 deletions
@@ -38,8 +38,10 @@ import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class StockClockController {
private static final String CLOCK_CLASS_NAME =
"com.android.systemui.statusbar.policy.QSClockIndicatorView";
private static final String[] CLOCK_CLASS_NAMES = {
"com.android.systemui.statusbar.policy.QSClockIndicatorView",
"com.android.systemui.statusbar.policy.Clock"
};
private final RuntimeContext runtimeContext;
private final Set<TextView> trackedClocks =
@@ -64,8 +66,25 @@ final class StockClockController {
return;
}
registerLayoutModeListenerIfNeeded();
Class<?> clockClass = ReflectionSupport.requireClass(CLOCK_CLASS_NAME, classLoader);
ArrayList<Class<?>> clockClasses = new ArrayList<>();
for (String className : CLOCK_CLASS_NAMES) {
Class<?> clockClass = ReflectionSupport.findClassIfExists(className, classLoader);
if (clockClass != null) {
clockClasses.add(clockClass);
}
}
if (clockClasses.isEmpty()) {
hooksInstalled = true;
return;
}
XposedInterface framework = runtimeContext.getFramework();
for (Class<?> clockClass : clockClasses) {
hookClockClass(framework, clockClass);
}
hooksInstalled = true;
}
private void hookClockClass(XposedInterface framework, Class<?> clockClass) {
XposedHookSupport.hookAllMethodsIfExists(framework, clockClass, "onAttachedToWindow", chain -> {
Object result = chain.proceed();
Object target = chain.getThisObject();
@@ -104,7 +123,7 @@ final class StockClockController {
}
return result;
});
XposedHookSupport.hookAllMethods(framework, clockClass, "notifyTimeChanged", chain -> {
XposedHookSupport.hookAllMethodsIfExists(framework, clockClass, "notifyTimeChanged", chain -> {
Object result = chain.proceed();
Object target = chain.getThisObject();
if (!(target instanceof TextView)) {
@@ -123,6 +142,14 @@ final class StockClockController {
trackAndApply(clockView, bellSound);
return result;
});
XposedHookSupport.hookAllMethodsIfExists(framework, clockClass, "updateClock", chain -> {
Object result = chain.proceed();
Object target = chain.getThisObject();
if (target instanceof TextView clockView) {
trackAndApply(clockView, null);
}
return result;
});
XposedHookSupport.hookAllMethodsIfExists(framework, clockClass, "setTextColor", chain -> {
Object result = chain.proceed();
if (chain.getThisObject() instanceof TextView clockView) {
@@ -137,7 +164,6 @@ final class StockClockController {
}
return result;
});
hooksInstalled = true;
}
private void reapplyClockIfCustomOrOwned(TextView clockView) {
@@ -162,6 +188,9 @@ final class StockClockController {
}
private void trackAndApply(TextView clockView, Object bellSound) {
if (isNotificationShadeDescendant(clockView)) {
return;
}
trackedClocks.add(clockView);
registerReceiverIfNeeded(clockView.getContext());
if (bellSound != null) {
@@ -219,6 +248,10 @@ final class StockClockController {
}
private void applyClockText(TextView clockView) {
if (isNotificationShadeDescendant(clockView)) {
restoreOwnedClock(clockView);
return;
}
SbtSettings settings = RuntimeSettingsCache.get(clockView.getContext());
boolean layoutEnabled = settings.clockEnabled;
if (layoutEnabled) {
@@ -330,6 +363,18 @@ final class StockClockController {
|| (settings.clockCustomFormatEnabled && !pattern.isEmpty());
}
private boolean isNotificationShadeDescendant(View view) {
View current = view;
while (current != null) {
if (current.getClass().getName().contains("NotificationShadeWindowView")) {
return true;
}
Object parent = current.getParent();
current = parent instanceof View ? (View) parent : null;
}
return false;
}
private void applyClockLineMode(TextView clockView) {
clockView.setSingleLine(true);
clockView.setHorizontallyScrolling(false);
@@ -43,8 +43,11 @@ final class StockUnlockedNotificationIconsController {
if (hooksInstalled || classLoader == null) {
return;
}
Class<?> containerClass = ReflectionSupport.requireClass(CONTAINER_CLASS_NAME, classLoader);
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onAttachedToWindow", chain -> {
Class<?> containerClass = ReflectionSupport.findClassIfExists(CONTAINER_CLASS_NAME, classLoader);
if (containerClass == null) {
return;
}
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), containerClass, "onAttachedToWindow", chain -> {
Object result = chain.proceed();
if (chain.getThisObject() instanceof View view) {
if (shouldManageContainer(view)) {
@@ -54,7 +57,7 @@ final class StockUnlockedNotificationIconsController {
}
return result;
});
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "calculateIconXTranslations", chain -> {
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), containerClass, "calculateIconXTranslations", chain -> {
if (chain.getThisObject() instanceof View view) {
if (shouldManageContainer(view)) {
trackContainer(view);
@@ -63,7 +66,7 @@ final class StockUnlockedNotificationIconsController {
}
return chain.proceed();
});
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onLayout", chain -> {
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), containerClass, "onLayout", chain -> {
Object result = chain.proceed();
if (chain.getThisObject() instanceof View view) {
if (shouldManageContainer(view)) {
@@ -75,7 +78,7 @@ final class StockUnlockedNotificationIconsController {
}
return result;
});
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "shouldForceOverflow", chain -> {
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), containerClass, "shouldForceOverflow", chain -> {
if (!(chain.getThisObject() instanceof View view)) {
return chain.proceed();
}
@@ -94,6 +94,7 @@ final class StockLayoutCanvasController {
private static final Set<String> TARGET_CLASS_SUBSTRINGS = Set.of(
"QSClockIndicatorView",
"statusbar.policy.Clock",
"SecShelfNotificationIconContainer"
);
@@ -638,13 +639,19 @@ final class StockLayoutCanvasController {
});
}
Class<?> clockClass = ReflectionSupport.findClassIfExists(
String[] clockClassNames = {
"com.android.systemui.statusbar.policy.QSClockIndicatorView",
classLoader);
if (clockClass != null) {
"com.android.systemui.statusbar.policy.Clock"
};
for (String className : clockClassNames) {
Class<?> clockClass = ReflectionSupport.findClassIfExists(className, classLoader);
if (clockClass == null) {
continue;
}
hookViewAppearanceInvalidation(clockClass, "onDarkChanged");
hookViewAppearanceInvalidation(clockClass, "setTextColor");
hookClockTextInvalidation(clockClass, "notifyTimeChanged");
hookClockTextInvalidation(clockClass, "updateClock");
hookClockTextInvalidation(clockClass, "setText");
hookViewLayoutInvalidation(clockClass, "onLayout");
}
@@ -317,7 +317,7 @@ final class UnlockedStockSourceCollector {
}
if (clockView == null
&& view instanceof TextView textView
&& view.getClass().getName().contains("QSClockIndicatorView")) {
&& isStatusbarClockView(textView)) {
clockView = textView;
}
if (statusEndContent == null && idName.equals("status_bar_end_side_content")) {
@@ -370,6 +370,12 @@ final class UnlockedStockSourceCollector {
carrierView);
}
private boolean isStatusbarClockView(TextView view) {
String className = view.getClass().getName();
return className.contains("QSClockIndicatorView")
|| className.equals("com.android.systemui.statusbar.policy.Clock");
}
private boolean isCarrierTextView(TextView view) {
if (view == null) {
return false;