Clean up post-AOD layout pipeline

This commit is contained in:
ajp_anton
2026-06-01 01:40:00 +00:00
parent 22dfdf2cb0
commit 9d7cb0b3f9
31 changed files with 1366 additions and 2581 deletions
@@ -1,26 +0,0 @@
package se.ajpanton.statusbartweak;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("se.ajpanton.statusbartweak", appContext.getPackageName());
}
}
@@ -16,7 +16,9 @@ public final class NotificationKeyReflection {
"mNotificationKey", "mNotificationKey",
"notificationKey", "notificationKey",
"mKey", "mKey",
"key" "key",
"mSlot",
"slot"
}; };
private NotificationKeyReflection() { private NotificationKeyReflection() {
@@ -53,6 +55,10 @@ public final class NotificationKeyReflection {
if (key != null) { if (key != null) {
return key; return key;
} }
key = nonEmptyStringFromMethod(view, "getSlot");
if (key != null) {
return key;
}
return nonEmptyStringFromFields(view, ICON_VIEW_KEY_FIELD_NAMES); return nonEmptyStringFromFields(view, ICON_VIEW_KEY_FIELD_NAMES);
} }
@@ -37,10 +37,6 @@ public final class RuntimeContext {
return modeStateRepository; return modeStateRepository;
} }
public boolean isLogEnabled() {
return RuntimeLogGate.isEnabled();
}
public void logWarning(String message, Throwable throwable) { public void logWarning(String message, Throwable throwable) {
logSplit(Log.WARN, message, throwable); logSplit(Log.WARN, message, throwable);
} }
@@ -50,7 +46,7 @@ public final class RuntimeContext {
} }
private void logSplit(int priority, String message, Throwable throwable) { private void logSplit(int priority, String message, Throwable throwable) {
if (!isLogEnabled()) { if (!RuntimeLogGate.isEnabled()) {
return; return;
} }
String safeMessage = message != null ? message : ""; String safeMessage = message != null ? message : "";
@@ -3,21 +3,14 @@ package se.ajpanton.statusbartweak.runtime.features.chips;
import android.app.KeyguardManager; import android.app.KeyguardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.TextView;
import java.util.ArrayDeque;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import se.ajpanton.statusbartweak.runtime.SystemContextProvider; import se.ajpanton.statusbartweak.runtime.SystemContextProvider;
import se.ajpanton.statusbartweak.runtime.ViewIdNames;
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext; import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
import se.ajpanton.statusbartweak.runtime.hooks.InstanceStateStore;
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport; import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
import se.ajpanton.statusbartweak.runtime.hooks.XposedHookSupport; import se.ajpanton.statusbartweak.runtime.hooks.XposedHookSupport;
import se.ajpanton.statusbartweak.runtime.settings.BroadcastReceiverSupport; import se.ajpanton.statusbartweak.runtime.settings.BroadcastReceiverSupport;
@@ -26,25 +19,12 @@ import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class StatusChipHider { final class StatusChipHider {
private static final String FIELD_FORCED_HIDDEN = "sbtStatusChipForcedHidden";
private static final String FIELD_PREV_VIS = "sbtStatusChipPrevVis";
private static final int TOP_REGION_DP = 220;
private static final int MAX_TEXT_SCAN_LEN = 160;
private static final int MAX_CLASS_SCAN_LEN = 480;
private static final int MAX_TEXT_NODES = 48;
private static final int MAX_ASCENT = 8;
private static final int ZONE_NONE = 0;
private static final int ZONE_TOP = 1;
private static final int KIND_UNKNOWN = 0; private static final int KIND_UNKNOWN = 0;
private static final int KIND_MEDIA = 1; private static final int KIND_MEDIA = 1;
private static final int KIND_NAV = 2; private static final int KIND_NAV = 2;
private static final int KIND_CALL = 3; private static final int KIND_CALL = 3;
private final RuntimeContext runtimeContext; private final RuntimeContext runtimeContext;
private final InstanceStateStore instanceStateStore = new InstanceStateStore();
private final Set<View> trackedRoots = Collections.newSetFromMap(new WeakHashMap<>());
private final Set<View> scannedRoots = Collections.newSetFromMap(new WeakHashMap<>());
private final Set<View> forcedHiddenViews = Collections.newSetFromMap(new WeakHashMap<>());
private final Set<Object> ongoingControllers = Collections.newSetFromMap(new WeakHashMap<>()); private final Set<Object> ongoingControllers = Collections.newSetFromMap(new WeakHashMap<>());
private boolean hooksInstalled; private boolean hooksInstalled;
@@ -69,8 +49,6 @@ final class StatusChipHider {
installBroadcastReceiver(SystemContextProvider.currentApplication()); installBroadcastReceiver(SystemContextProvider.currentApplication());
refreshSettings(); refreshSettings();
installOngoingActivityHooks(classLoader); installOngoingActivityHooks(classLoader);
installTouchInterceptHooks(classLoader);
installViewRootHooks();
hooksInstalled = true; hooksInstalled = true;
} }
@@ -100,7 +78,6 @@ final class StatusChipHider {
refreshSettings(); refreshSettings();
if (isAnyChipHidingEnabled()) { if (isAnyChipHidingEnabled()) {
refreshOngoingActivityController(controller); refreshOngoingActivityController(controller);
rescanTrackedRoots();
} }
} }
return result; return result;
@@ -130,87 +107,8 @@ final class StatusChipHider {
return result; return result;
} }
Object data = chain.getArg(1); Object data = chain.getArg(1);
boolean suppress = shouldHide(classifyOngoingData(data), ZONE_TOP); int kind = classifyOngoingData(data);
return suppress ? true : result; return shouldHideEnabledKind(kind) ? true : result;
});
}
private void installViewRootHooks() {
Class<?> viewRootClass = ReflectionSupport.requireClass("android.view.ViewRootImpl", null);
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), viewRootClass, "performTraversals", chain -> {
Object result = chain.proceed();
Object rootObj = ReflectionSupport.requireFieldValue(chain.getThisObject(), "mView");
if (!(rootObj instanceof View root)) {
return result;
}
installBroadcastReceiver(root.getContext());
trackedRoots.add(root);
if (!isAnyChipHidingEnabled()) {
restoreForcedHiddenViews();
return result;
}
if (scannedRoots.add(root)) {
applyToViewTree(root);
} else {
keepForcedHiddenViewsHidden();
}
return result;
});
}
private void installTouchInterceptHooks(ClassLoader classLoader) {
Class<?> targetClass = ReflectionSupport.findClassIfExists(
"com.android.systemui.statusbar.phone.TouchInterceptFrameLayout",
classLoader
);
if (targetClass == null) {
return;
}
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), targetClass, "onLayout", chain -> {
Object result = chain.proceed();
if (!isAnyChipHidingEnabled()) {
return result;
}
if (!(chain.getThisObject() instanceof View view)) {
return result;
}
if (view.getWidth() > 0 && view.getHeight() > 0) {
applySourceDecision(view);
}
return result;
});
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), targetClass, "onAttachedToWindow", chain -> {
Object result = chain.proceed();
if (!isAnyChipHidingEnabled()) {
return result;
}
if (chain.getThisObject() instanceof View view && shouldPreemptivelyHide(view)) {
forceHide(view);
}
return result;
});
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), targetClass, "setVisibility", chain -> {
if (!(chain.getThisObject() instanceof View view)) {
return chain.proceed();
}
if (isAnyChipHidingEnabled()
&& !chain.getArgs().isEmpty()
&& chain.getArg(0) instanceof Integer requestedVisibility
&& requestedVisibility != View.GONE
&& shouldPreemptivelyHide(view)) {
markForcedHidden(view, requestedVisibility);
Object[] args = chain.getArgs().toArray();
args[0] = View.GONE;
return chain.proceed(args);
}
Object result = chain.proceed();
if (!isAnyChipHidingEnabled()) {
return result;
}
if (view.getWidth() > 0 && view.getHeight() > 0) {
applySourceDecision(view);
}
return result;
}); });
} }
@@ -226,9 +124,7 @@ final class StatusChipHider {
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
RuntimeSettingsCache.invalidate(); RuntimeSettingsCache.invalidate();
refreshSettings(); refreshSettings();
scannedRoots.clear();
refreshOngoingActivityLists(); refreshOngoingActivityLists();
rescanTrackedRoots();
} }
}; };
BroadcastReceiverSupport.registerExportedOnApplicationContext( BroadcastReceiverSupport.registerExportedOnApplicationContext(
@@ -260,19 +156,6 @@ final class StatusChipHider {
return hideAll || hideMediaUnlocked || hideNavUnlocked || hideCallUnlocked; return hideAll || hideMediaUnlocked || hideNavUnlocked || hideCallUnlocked;
} }
private void rescanTrackedRoots() {
if (!isAnyChipHidingEnabled()) {
restoreForcedHiddenViews();
return;
}
for (View root : trackedRoots) {
if (root != null) {
scannedRoots.add(root);
applyToViewTree(root);
}
}
}
private void refreshOngoingActivityLists() { private void refreshOngoingActivityLists() {
if (ongoingActivityDataHelperClass == null || notificationLockscreenUserManagerClass == null) { if (ongoingActivityDataHelperClass == null || notificationLockscreenUserManagerClass == null) {
return; return;
@@ -315,200 +198,14 @@ final class StatusChipHider {
boolean sawItem = false; boolean sawItem = false;
for (Object data : iterable) { for (Object data : iterable) {
sawItem = true; sawItem = true;
if (!shouldHide(classifyOngoingData(data), ZONE_TOP)) { if (!shouldHideEnabledKind(classifyOngoingData(data))) {
return false; return false;
} }
} }
return sawItem; return sawItem;
} }
private void applyToViewTree(View root) { private boolean shouldHideEnabledKind(int kind) {
ArrayDeque<View> stack = new ArrayDeque<>();
stack.push(root);
while (!stack.isEmpty()) {
View source = stack.pop();
if (source == null) {
continue;
}
if (source instanceof ViewGroup group) {
for (int index = group.getChildCount() - 1; index >= 0; index--) {
stack.push(group.getChildAt(index));
}
}
applySourceDecision(source);
}
}
private boolean applySourceDecision(View source) {
if (source == null) {
return false;
}
int zone = detectZone(source);
if (zone == ZONE_NONE || !isSourceCandidate(source)) {
restoreIfForcedHidden(source);
return false;
}
View target = resolveHideTarget(source, zone);
if (target == null) {
restoreIfForcedHidden(source);
return false;
}
int targetZone = detectZone(target);
if (targetZone == ZONE_NONE) {
restoreIfForcedHidden(target);
return false;
}
String sourceText = collectText(source);
String targetText = target == source ? sourceText : collectText(target);
String kindText = sourceText.isEmpty() ? targetText : sourceText;
String classNames = target == source
? collectClassNames(source)
: collectClassNames(source) + " " + collectClassNames(target);
String lowerText = kindText.toLowerCase(Locale.ROOT);
if (looksLikePrivacy(target, kindText) || isDefinitelyNotChipText(lowerText)) {
restoreIfForcedHidden(target);
return false;
}
int kind = classifyKind(source, kindText, classNames);
if (shouldHide(kind, targetZone)) {
forceHide(target);
return true;
} else {
restoreIfForcedHidden(target);
return false;
}
}
private boolean shouldPreemptivelyHide(View source) {
if (source == null) {
return false;
}
if (isForcedHidden(source) && shouldHideTopUnlocked()) {
return true;
}
if (!isTransitionSourceCandidate(source)) {
return false;
}
return shouldHideSource(source, true);
}
private boolean shouldHideSource(View source, boolean allowRelaxedGeometry) {
int zone = detectZone(source);
boolean relaxedGeometry = false;
if (zone == ZONE_NONE) {
if (!allowRelaxedGeometry || !isTransitionSourceCandidate(source)) {
return false;
}
if (source.getWidth() > 0 && source.getHeight() > 0) {
return false;
}
zone = ZONE_TOP;
relaxedGeometry = true;
} else if (!isSourceCandidate(source)) {
return false;
}
String sourceText = collectText(source);
String lowerText = sourceText.toLowerCase(Locale.ROOT);
if (looksLikePrivacy(source, sourceText) || isDefinitelyNotChipText(lowerText)) {
return false;
}
int kind = classifyKind(source, sourceText, collectClassNames(source));
if (relaxedGeometry && kind == KIND_UNKNOWN && lowerText.isEmpty()) {
return false;
}
return shouldHide(kind, zone);
}
private boolean isSourceCandidate(View view) {
return isTransitionSourceCandidate(view) && looksLikeChipGeometry(view);
}
private boolean isTransitionSourceCandidate(View view) {
if (isOngoingActivityCapsule(view)) {
return false;
}
if (!isSystemUiView(view)) {
return false;
}
String className = className(view).toLowerCase(Locale.ROOT);
if (className.contains("privacy") || isDefinitelyNotChipClass(className)) {
return false;
}
return isChipClassName(className);
}
private View resolveHideTarget(View source, int sourceZone) {
String sourceClass = className(source).toLowerCase(Locale.ROOT);
if (sourceClass.contains("touchinterceptframelayout")) {
return source;
}
View best = null;
View current = source;
int depth = 0;
int screenWidth = source.getResources().getDisplayMetrics().widthPixels;
while (current != null && depth < MAX_ASCENT) {
if (!isSystemUiView(current)) {
break;
}
if (detectZone(current) != sourceZone) {
break;
}
if (looksLikeHideTarget(current, source, screenWidth)) {
best = current;
}
ViewParent parent = current.getParent();
current = parent instanceof View view ? view : null;
depth++;
}
return best;
}
private boolean looksLikeHideTarget(View candidate, View source, int screenWidth) {
if (!looksLikeChipGeometry(candidate)) {
return false;
}
String className = className(candidate).toLowerCase(Locale.ROOT);
if (className.contains("privacy") || isDefinitelyNotChipClass(className)) {
return false;
}
if (!isChipClassName(className)) {
return false;
}
int width = candidate.getWidth();
int height = candidate.getHeight();
if (width >= (int) (screenWidth * 0.98f) && height < dp(candidate, 90)) {
return false;
}
if (candidate == source) {
return true;
}
return candidate instanceof ViewGroup && width >= source.getWidth();
}
private boolean isChipClassName(String lowerClass) {
return lowerClass.contains("chip")
|| lowerClass.contains("ongoing")
|| lowerClass.contains("statusevent")
|| lowerClass.contains("touchinterceptframelayout");
}
private int detectZone(View view) {
if (view == null || view.getWidth() <= 0 || view.getHeight() <= 0) {
return ZONE_NONE;
}
int[] location = new int[2];
try {
view.getLocationOnScreen(location);
} catch (Throwable ignored) {
return ZONE_NONE;
}
return location[1] >= 0 && location[1] <= dp(view, TOP_REGION_DP) ? ZONE_TOP : ZONE_NONE;
}
private boolean shouldHide(int kind, int zone) {
if (zone != ZONE_TOP || !shouldHideTopUnlocked()) {
return false;
}
if (hideAll && kind == KIND_UNKNOWN) { if (hideAll && kind == KIND_UNKNOWN) {
return true; return true;
} }
@@ -528,13 +225,10 @@ final class StatusChipHider {
return isAnyChipHidingEnabled() && !isKeyguardLocked(); return isAnyChipHidingEnabled() && !isKeyguardLocked();
} }
private int classifyKind(View view, String text, String classNames) { private int classifyKind(String text, String classNames) {
String lowerText = text != null ? text.toLowerCase(Locale.ROOT) : ""; String lowerText = text != null ? text.toLowerCase(Locale.ROOT) : "";
String lowerClass = classNames != null && !classNames.isEmpty() String lowerClass = classNames != null ? classNames.toLowerCase(Locale.ROOT) : "";
? classNames.toLowerCase(Locale.ROOT)
: (view != null ? className(view).toLowerCase(Locale.ROOT) : "");
if (containsToken(lowerText, "call") if (containsToken(lowerText, "call")
|| containsPhrase(lowerText, "ongoing call")
|| lowerClass.contains("call")) { || lowerClass.contains("call")) {
return KIND_CALL; return KIND_CALL;
} }
@@ -577,188 +271,7 @@ final class StatusChipHider {
+ textField(data, "mSecondaryInfo") + " " + textField(data, "mSecondaryInfo") + " "
+ textField(data, "mDescription") + " " + textField(data, "mDescription") + " "
+ textField(data, "mExpandedChipText")).trim(); + textField(data, "mExpandedChipText")).trim();
return classifyKind(null, text, data.getClass().getName()); return classifyKind(text, data.getClass().getName());
}
private boolean looksLikePrivacy(View view, String text) {
String lowerClass = className(view).toLowerCase(Locale.ROOT);
String lowerText = text != null ? text.toLowerCase(Locale.ROOT) : "";
return lowerClass.contains("privacy")
|| containsToken(lowerText, "camera")
|| containsToken(lowerText, "microphone")
|| containsPhrase(lowerText, "location in use")
|| containsPhrase(lowerText, "mic in use");
}
private String collectClassNames(View root) {
StringBuilder out = new StringBuilder();
appendClassName(out, root);
if (!(root instanceof ViewGroup)) {
return out.toString();
}
ArrayDeque<View> stack = new ArrayDeque<>();
stack.push(root);
int nodes = 0;
while (!stack.isEmpty() && out.length() < MAX_CLASS_SCAN_LEN && nodes < MAX_TEXT_NODES) {
View current = stack.pop();
nodes++;
if (current != root) {
appendClassName(out, current);
}
if (current instanceof ViewGroup group) {
for (int index = 0; index < group.getChildCount(); index++) {
stack.push(group.getChildAt(index));
}
}
}
return out.toString();
}
private String collectText(View root) {
StringBuilder out = new StringBuilder();
appendText(out, root.getContentDescription());
if (root instanceof TextView textView) {
appendText(out, textView.getText());
}
if (!(root instanceof ViewGroup)) {
return out.toString();
}
ArrayDeque<View> stack = new ArrayDeque<>();
stack.push(root);
int nodes = 0;
while (!stack.isEmpty() && out.length() < MAX_TEXT_SCAN_LEN && nodes < MAX_TEXT_NODES) {
View current = stack.pop();
nodes++;
if (current != root) {
appendText(out, current.getContentDescription());
if (current instanceof TextView textView) {
appendText(out, textView.getText());
}
}
if (current instanceof ViewGroup group) {
for (int index = 0; index < group.getChildCount(); index++) {
stack.push(group.getChildAt(index));
}
}
}
return out.toString();
}
private void forceHide(View view) {
int restoreVisibility = view.getVisibility() != View.GONE ? view.getVisibility() : View.VISIBLE;
markForcedHidden(view, restoreVisibility);
if (view.getVisibility() != View.GONE) {
view.setVisibility(View.GONE);
}
}
private void keepForcedHiddenViewsHidden() {
if (forcedHiddenViews.isEmpty()) {
return;
}
ArrayDeque<View> staleViews = new ArrayDeque<>();
for (View view : forcedHiddenViews) {
if (view == null || !view.isAttachedToWindow()) {
staleViews.add(view);
continue;
}
if (view.getVisibility() != View.GONE) {
view.setVisibility(View.GONE);
}
}
while (!staleViews.isEmpty()) {
forcedHiddenViews.remove(staleViews.removeFirst());
}
}
private void restoreForcedHiddenViews() {
if (forcedHiddenViews.isEmpty()) {
return;
}
ArrayDeque<View> views = new ArrayDeque<>(forcedHiddenViews);
while (!views.isEmpty()) {
restoreIfForcedHidden(views.removeFirst());
}
}
private void markForcedHidden(View view, int restoreVisibility) {
instanceStateStore.put(view, FIELD_PREV_VIS, restoreVisibility);
instanceStateStore.put(view, FIELD_FORCED_HIDDEN, Boolean.TRUE);
forcedHiddenViews.add(view);
}
private void restoreIfForcedHidden(View view) {
if (!isForcedHidden(view)) {
return;
}
Object previous = instanceStateStore.get(view, FIELD_PREV_VIS);
int restoreVisibility = previous instanceof Integer integer ? integer : View.VISIBLE;
instanceStateStore.remove(view, FIELD_FORCED_HIDDEN);
instanceStateStore.remove(view, FIELD_PREV_VIS);
forcedHiddenViews.remove(view);
if (view.getVisibility() != restoreVisibility) {
view.setVisibility(restoreVisibility);
}
if (restoreVisibility == View.VISIBLE && view.getAlpha() == 0f) {
view.setAlpha(1f);
}
}
private boolean isForcedHidden(View view) {
Object marker = instanceStateStore.get(view, FIELD_FORCED_HIDDEN);
return marker instanceof Boolean bool && bool;
}
private boolean isSystemUiView(View view) {
return className(view).contains("systemui");
}
private boolean looksLikeChipGeometry(View view) {
if (view == null || view.getWidth() <= 0 || view.getHeight() <= 0) {
return false;
}
int width = view.getWidth();
int height = view.getHeight();
int screenWidth = view.getResources().getDisplayMetrics().widthPixels;
if (height < dp(view, 18) || height > dp(view, 160)) {
return false;
}
if (width < height * 2) {
return false;
}
return !(width > (int) (screenWidth * 0.95f) && height < dp(view, 110));
}
private boolean isDefinitelyNotChipClass(String lowerClass) {
return lowerClass.contains("clock")
|| lowerClass.contains("date")
|| lowerClass.contains("brightness")
|| lowerClass.contains("tile")
|| lowerClass.contains("qsbuttonscontainer")
|| lowerClass.contains("sectionheaderview")
|| lowerClass.contains("expandablenotificationrow")
|| lowerClass.contains("carrier")
|| lowerClass.contains("statusicon")
|| lowerClass.contains("indicator")
|| lowerClass.contains("launchabletextview")
|| lowerClass.contains("qsshortendate")
|| lowerClass.contains("qsclock")
|| lowerClass.contains("quickqs");
}
private boolean isDefinitelyNotChipText(String lowerText) {
if (lowerText == null || lowerText.isEmpty()) {
return false;
}
return containsPhrase(lowerText, "notification settings")
|| containsToken(lowerText, "brightness")
|| containsToken(lowerText, "wifi")
|| containsPhrase(lowerText, "smart view")
|| containsToken(lowerText, "mirror");
}
private String className(View view) {
return view != null && view.getClass() != null ? view.getClass().getName() : "";
} }
private String textField(Object target, String fieldName) { private String textField(Object target, String fieldName) {
@@ -766,44 +279,6 @@ final class StatusChipHider {
return value != null ? String.valueOf(value) : ""; return value != null ? String.valueOf(value) : "";
} }
private boolean isOngoingActivityCapsule(View view) {
return ViewIdNames.hasIdName(view, "ongoing_activity_capsule");
}
private void appendText(StringBuilder out, CharSequence value) {
if (value == null || value.length() == 0 || out.length() >= MAX_TEXT_SCAN_LEN) {
return;
}
if (out.length() > 0) {
out.append(' ');
}
int remaining = MAX_TEXT_SCAN_LEN - out.length();
if (value.length() > remaining) {
out.append(value, 0, remaining);
} else {
out.append(value);
}
}
private void appendClassName(StringBuilder out, View view) {
if (view == null || out.length() >= MAX_CLASS_SCAN_LEN) {
return;
}
String value = className(view);
if (value.isEmpty()) {
return;
}
if (out.length() > 0) {
out.append(' ');
}
int remaining = MAX_CLASS_SCAN_LEN - out.length();
if (value.length() > remaining) {
out.append(value, 0, remaining);
} else {
out.append(value);
}
}
private boolean containsAny(String value, String... needles) { private boolean containsAny(String value, String... needles) {
if (value == null || value.isEmpty()) { if (value == null || value.isEmpty()) {
return false; return false;
@@ -816,10 +291,6 @@ final class StatusChipHider {
return false; return false;
} }
private boolean containsPhrase(String value, String phrase) {
return value != null && phrase != null && value.contains(phrase);
}
private boolean containsToken(String value, String token) { private boolean containsToken(String value, String token) {
if (value == null || value.isEmpty() || token == null || token.isEmpty()) { if (value == null || value.isEmpty() || token == null || token.isEmpty()) {
return false; return false;
@@ -850,10 +321,6 @@ final class StatusChipHider {
return value != null && !value.isEmpty() && value.matches(".*\\b\\d+\\s*(m|km|mi|ft)\\b.*"); return value != null && !value.isEmpty() && value.matches(".*\\b\\d+\\s*(m|km|mi|ft)\\b.*");
} }
private int dp(View view, int dp) {
return Math.round(dp * view.getResources().getDisplayMetrics().density);
}
private boolean isKeyguardLocked() { private boolean isKeyguardLocked() {
try { try {
Context context = SystemContextProvider.currentApplication(); Context context = SystemContextProvider.currentApplication();
@@ -876,4 +343,5 @@ final class StatusChipHider {
} }
return keyguardManager; return keyguardManager;
} }
} }
@@ -63,6 +63,10 @@ final class LockscreenCardsNotificationRowFilter {
} }
} }
boolean hasHiddenRows() {
return !hiddenRows.isEmpty();
}
void suppressHiddenRows() { void suppressHiddenRows() {
if (hiddenRows.isEmpty()) { if (hiddenRows.isEmpty()) {
return; return;
@@ -16,11 +16,13 @@ import android.widget.TextView;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -42,6 +44,8 @@ import se.ajpanton.statusbartweak.runtime.render.AodStatusbarSourceStore;
import se.ajpanton.statusbartweak.runtime.render.DebugBoundsOverlayController; import se.ajpanton.statusbartweak.runtime.render.DebugBoundsOverlayController;
import se.ajpanton.statusbartweak.runtime.render.LockscreenCardsNotificationIconSourceStore; import se.ajpanton.statusbartweak.runtime.render.LockscreenCardsNotificationIconSourceStore;
import se.ajpanton.statusbartweak.runtime.render.LockscreenCardsNotificationStripRenderer; import se.ajpanton.statusbartweak.runtime.render.LockscreenCardsNotificationStripRenderer;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationActiveKeyStore;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker;
import se.ajpanton.statusbartweak.runtime.render.OwnedIconHostManager; import se.ajpanton.statusbartweak.runtime.render.OwnedIconHostManager;
import se.ajpanton.statusbartweak.runtime.render.UnlockedIconSnapshotRenderController; import se.ajpanton.statusbartweak.runtime.render.UnlockedIconSnapshotRenderController;
import se.ajpanton.statusbartweak.runtime.render.UnlockedIconSnapshotRenderController.RenderResult; import se.ajpanton.statusbartweak.runtime.render.UnlockedIconSnapshotRenderController.RenderResult;
@@ -94,19 +98,7 @@ final class StockLayoutCanvasController {
"notification_icon_area_inner", "notification_icon_area_inner",
"notificationIcons" "notificationIcons"
); );
private static final int STATUS_BAR_STATE_SHADE_LOCKED = 2;
private static final Set<String> LAYOUT_OFF_EXTRA_RECOVERABLE_IDS = Set.of(
"system_icon_area",
"statusIcons",
"battery"
);
private static final Set<String> LAYOUT_OFF_RECOVERABLE_CLASS_SUBSTRINGS = Set.of(
"NotificationIconContainer",
"StatusIconContainer",
"BatteryMeterView",
"QSClockIndicatorView"
);
private final RuntimeContext runtimeContext; private final RuntimeContext runtimeContext;
private final Map<View, HiddenViewState> hiddenViewStates = new WeakHashMap<>(); private final Map<View, HiddenViewState> hiddenViewStates = new WeakHashMap<>();
@@ -172,6 +164,7 @@ final class StockLayoutCanvasController {
private boolean hooksInstalled; private boolean hooksInstalled;
private int ownHiddenViewAlphaWriteDepth; private int ownHiddenViewAlphaWriteDepth;
private boolean notificationDrawerWasOpen;
StockLayoutCanvasController(RuntimeContext runtimeContext) { StockLayoutCanvasController(RuntimeContext runtimeContext) {
this.runtimeContext = runtimeContext; this.runtimeContext = runtimeContext;
@@ -184,6 +177,8 @@ final class StockLayoutCanvasController {
new LockscreenCardsNotificationStripRenderer(); new LockscreenCardsNotificationStripRenderer();
unlockedIconRenderController = new UnlockedIconSnapshotRenderController(); unlockedIconRenderController = new UnlockedIconSnapshotRenderController();
runtimeContext.getModeStateRepository().addSceneListener(this::scheduleSceneRefresh); runtimeContext.getModeStateRepository().addSceneListener(this::scheduleSceneRefresh);
runtimeContext.getModeStateRepository().addSystemUiStatusBarStateListener(
this::handleSystemUiStatusBarStateChanged);
} }
void install(ClassLoader classLoader) { void install(ClassLoader classLoader) {
@@ -194,12 +189,147 @@ final class StockLayoutCanvasController {
installCardsNotificationIconSourceHook(classLoader); installCardsNotificationIconSourceHook(classLoader);
installLockscreenCardsNotificationRowFilterHook(classLoader); installLockscreenCardsNotificationRowFilterHook(classLoader);
installUnlockedAppearanceInvalidationHooks(classLoader); installUnlockedAppearanceInvalidationHooks(classLoader);
installNotificationCollectionHooks(classLoader);
statusIconModelTracker.installHooks(classLoader); statusIconModelTracker.installHooks(classLoader);
installShadeExpansionHooks(classLoader);
installShadeHeaderAnimationGuardHook(classLoader); installShadeHeaderAnimationGuardHook(classLoader);
installViewRootHook(classLoader); installViewRootHook(classLoader);
hooksInstalled = true; hooksInstalled = true;
} }
private void installNotificationCollectionHooks(ClassLoader classLoader) {
for (String className : List.of(
"com.android.systemui.statusbar.notification.collection.NotifCollection",
"com.android.systemui.statusbar.notification.NotificationEntryManager")) {
Class<?> type = ReflectionSupport.findClassIfExists(className, classLoader);
if (type == null) {
continue;
}
for (Method method : type.getDeclaredMethods()) {
String lowerName = method.getName().toLowerCase(Locale.ROOT);
if (!isNotificationCollectionMutationMethod(lowerName)) {
continue;
}
method.setAccessible(true);
runtimeContext.getFramework().hook(method).intercept(chain -> {
Object result = chain.proceed();
refreshActiveNotificationKeysFromCollection(chain.getThisObject());
return result;
});
}
}
}
private boolean isNotificationCollectionMutationMethod(String lowerName) {
boolean subject = lowerName.contains("notification")
|| lowerName.contains("notif")
|| lowerName.contains("entry");
boolean mutation = lowerName.contains("add")
|| lowerName.contains("post")
|| lowerName.contains("update")
|| lowerName.contains("remove")
|| lowerName.contains("dismiss")
|| lowerName.contains("cancel")
|| lowerName.contains("cleanup")
|| lowerName.contains("clean")
|| lowerName.contains("clear");
return subject
&& mutation
&& !lowerName.contains("listener")
&& !lowerName.contains("lifetime")
&& !lowerName.contains("interceptor");
}
private void installShadeExpansionHooks(ClassLoader classLoader) {
for (String className : List.of(
"com.android.systemui.shade.ShadeExpansionStateManager",
"com.android.systemui.shade.NotificationPanelViewController",
"com.android.systemui.statusbar.phone.NotificationPanelViewController")) {
Class<?> type = ReflectionSupport.findClassIfExists(className, classLoader);
if (type == null) {
continue;
}
for (Method method : type.getDeclaredMethods()) {
String lowerName = method.getName().toLowerCase(Locale.ROOT);
if (!lowerName.contains("expansion") && !lowerName.contains("expandedheight")) {
continue;
}
method.setAccessible(true);
runtimeContext.getFramework().hook(method).intercept(chain -> {
Object result = chain.proceed();
handleShadeExpansionHookCall(chain.getThisObject(), chain.getArgs());
return result;
});
}
}
}
private void handleShadeExpansionHookCall(Object target, List<Object> args) {
SceneKey activeScene = runtimeContext.getModeStateRepository().getActiveScene();
if (activeScene == null || !activeScene.isUnlocked()) {
return;
}
Float expansion = firstExpansionFraction(args);
if (expansion == null) {
expansion = reflectedExpansion(target);
}
if (expansion == null) {
return;
}
if (expansion <= 0.01f) {
notificationDrawerWasOpen = false;
return;
}
if (expansion <= 0.05f) {
return;
}
markNotificationDrawerSeen();
}
private Float firstExpansionFraction(List<Object> args) {
if (args == null || args.isEmpty()) {
return null;
}
for (Object arg : args) {
Float value = fractionValue(arg);
if (value == null) {
value = reflectedFraction(arg);
}
if (value != null) {
return value;
}
}
return null;
}
private void markNotificationDrawerSeen() {
if (notificationDrawerWasOpen) {
return;
}
notificationDrawerWasOpen = true;
boolean changed = NotificationUnreadTracker.markSeen();
if (changed) {
scheduleUnlockedAppearanceRefreshForAllRoots();
}
}
private void handleSystemUiStatusBarStateChanged(
int previousState,
int currentState,
boolean dozing
) {
if (dozing) {
return;
}
if (currentState == STATUS_BAR_STATE_SHADE_LOCKED
&& previousState != STATUS_BAR_STATE_SHADE_LOCKED) {
markNotificationDrawerSeen();
} else if (previousState == STATUS_BAR_STATE_SHADE_LOCKED
&& currentState != STATUS_BAR_STATE_SHADE_LOCKED) {
notificationDrawerWasOpen = false;
}
}
private void installShadeHeaderAnimationGuardHook(ClassLoader classLoader) { private void installShadeHeaderAnimationGuardHook(ClassLoader classLoader) {
Class<?> viewClass = ReflectionSupport.requireClass("android.view.View", classLoader); Class<?> viewClass = ReflectionSupport.requireClass("android.view.View", classLoader);
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "setAlpha", chain -> { XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "setAlpha", chain -> {
@@ -494,6 +624,9 @@ final class StockLayoutCanvasController {
methodName, methodName,
chain -> { chain -> {
ViewGroup parent = chain.getThisObject() instanceof ViewGroup group ? group : null; ViewGroup parent = chain.getThisObject() instanceof ViewGroup group ? group : null;
if (parent != null && !isLayoutEnabled(parent.getContext())) {
return chain.proceed();
}
View child = firstArg(chain.getArgs()) instanceof View view ? view : null; View child = firstArg(chain.getArgs()) instanceof View view ? view : null;
View rootBefore = parent != null ? unlockedStatusBarRootFor(parent) : null; View rootBefore = parent != null ? unlockedStatusBarRootFor(parent) : null;
boolean affectedBefore = isStatusChipTreeMutation(parent, child); boolean affectedBefore = isStatusChipTreeMutation(parent, child);
@@ -541,17 +674,21 @@ final class StockLayoutCanvasController {
return chain.proceed(); return chain.proceed();
} }
if (!isLayoutEnabled(container.getContext())) { if (!isLayoutEnabled(container.getContext())) {
Object result = chain.proceed(); return chain.proceed();
LockscreenCardsNotificationIconSourceStore.put(container, new ArrayList<>());
return result;
}
if (!isCardsNotificationIconSourceContainer(container)) {
Object result = chain.proceed();
markUnlockedLayoutDirty(container);
return result;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Function<Object, Object> original = (Function<Object, Object>) args.get(functionIndex); Function<Object, Object> original = (Function<Object, Object>) args.get(functionIndex);
if (!isCardsNotificationIconSourceContainer(container)) {
Function<Object, Object> wrapped = entryObj -> {
recordNotificationEntry(entryObj);
return original.apply(entryObj);
};
Object[] newArgs = args.toArray(new Object[0]);
newArgs[functionIndex] = wrapped;
Object result = chain.proceed(newArgs);
requestUnlockedLayoutRefreshFromSource(container);
return result;
}
ArrayList<LockscreenCardsNotificationIconSourceStore.SourceEntry> captured = ArrayList<LockscreenCardsNotificationIconSourceStore.SourceEntry> captured =
new ArrayList<>(); new ArrayList<>();
Function<Object, Object> wrapped = entryObj -> { Function<Object, Object> wrapped = entryObj -> {
@@ -563,6 +700,7 @@ final class StockLayoutCanvasController {
return null; return null;
} }
Object result = original.apply(entryObj); Object result = original.apply(entryObj);
recordNotificationEntry(entryObj);
if (result == null) { if (result == null) {
result = fallbackStatusBarIcon(entryObj); result = fallbackStatusBarIcon(entryObj);
} }
@@ -578,6 +716,7 @@ final class StockLayoutCanvasController {
newArgs[functionIndex] = wrapped; newArgs[functionIndex] = wrapped;
Object result = chain.proceed(newArgs); Object result = chain.proceed(newArgs);
LockscreenCardsNotificationIconSourceStore.put(container, captured); LockscreenCardsNotificationIconSourceStore.put(container, captured);
requestUnlockedLayoutRefreshFromSource(container);
return result; return result;
}); });
} }
@@ -711,11 +850,39 @@ final class StockLayoutCanvasController {
private void captureAodPackagesFromNotifCollection(Object wrapper) { private void captureAodPackagesFromNotifCollection(Object wrapper) {
Object collection = ReflectionSupport.getFieldValue(wrapper, "mNotifCollection"); Object collection = ReflectionSupport.getFieldValue(wrapper, "mNotifCollection");
ArrayList<StatusBarNotification> notifications = notificationsFromNotifCollection(collection); if (collection == null) {
if (notifications.isEmpty()) {
return; return;
} }
ArrayList<StatusBarNotification> notifications = notificationsFromNotifCollection(collection);
if (notifications.isEmpty()) {
latestAodNotifications = new ArrayList<>();
latestAodIconImageViews = new ArrayList<>();
NotificationActiveKeyStore.replace(Collections.emptySet());
NotificationUnreadTracker.retainActiveKeys(Collections.emptySet());
LockscreenCardsNotificationIconSourceStore.clearAodSources();
markKnownAodNotificationRootsDirty();
updateKnownAodNotificationSources();
return;
}
boolean changed = false;
ArrayList<String> packages = new ArrayList<>();
HashSet<String> activeKeys = new HashSet<>();
for (StatusBarNotification sbn : notifications) {
changed |= NotificationUnreadTracker.record(sbn);
if (sbn != null && sbn.getKey() != null) {
activeKeys.add(sbn.getKey());
}
if (sbn != null && AppIconRules.isValidPackageName(sbn.getPackageName())) {
packages.add(sbn.getPackageName());
}
}
updateActiveNotificationKeys(activeNotificationIconKeys(notifications));
changed |= NotificationUnreadTracker.retainActiveKeys(activeKeys);
LockscreenCardsNotificationIconSourceStore.putAodNotificationPackages(packages);
latestAodNotifications = notifications; latestAodNotifications = notifications;
if (changed) {
markKnownAodNotificationRootsDirty();
}
updateKnownAodNotificationSources(); updateKnownAodNotificationSources();
} }
@@ -787,6 +954,52 @@ final class StockLayoutCanvasController {
notifications.add(sbn); notifications.add(sbn);
} }
private boolean recordNotificationEntry(Object entry) {
StatusBarNotification sbn = NotificationReflection.statusBarNotificationEntry(entry);
return NotificationUnreadTracker.record(sbn);
}
private void refreshActiveNotificationKeysFromCollection(Object collection) {
ArrayList<StatusBarNotification> notifications = notificationsFromNotifCollection(collection);
if (notifications.isEmpty()) {
return;
}
for (StatusBarNotification sbn : notifications) {
if (sbn != null && sbn.getKey() != null && AppIconRules.isValidPackageName(sbn.getPackageName())) {
NotificationUnreadTracker.record(sbn);
}
}
updateActiveNotificationKeys(activeNotificationIconKeys(notifications));
}
private void updateActiveNotificationKeys(ArrayList<String> keys) {
if (!NotificationActiveKeyStore.replace(keys)) {
return;
}
requestUnlockedLayoutRefreshForAllRoots();
markKnownAodNotificationRootsDirty();
}
private ArrayList<String> activeNotificationIconKeys(ArrayList<StatusBarNotification> notifications) {
ArrayList<String> keys = new ArrayList<>();
if (notifications == null) {
return keys;
}
for (StatusBarNotification sbn : notifications) {
if (sbn == null || !AppIconRules.isValidPackageName(sbn.getPackageName())) {
continue;
}
if (sbn.getKey() != null) {
keys.add(sbn.getKey());
}
String packageName = sbn.getPackageName();
int id = sbn.getId();
keys.add(packageName + "/" + id);
keys.add(packageName + "/0x" + Integer.toHexString(id));
}
return keys;
}
private void installViewRootHook(ClassLoader classLoader) { private void installViewRootHook(ClassLoader classLoader) {
Class<?> viewRootClass = ReflectionSupport.requireClass("android.view.ViewRootImpl", classLoader); Class<?> viewRootClass = ReflectionSupport.requireClass("android.view.ViewRootImpl", classLoader);
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), viewRootClass, "performDraw", chain -> { XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), viewRootClass, "performDraw", chain -> {
@@ -838,6 +1051,9 @@ final class StockLayoutCanvasController {
if (activeScene == null) { if (activeScene == null) {
return; return;
} }
if (!runtimeContext.getModeStateRepository().isSystemUiShadeLocked() && !activeScene.isAod()) {
notificationDrawerWasOpen = false;
}
if (isNotificationShadeWindowRoot(root)) { if (isNotificationShadeWindowRoot(root)) {
if (shouldPrepareCarrierlessAodNotificationTransition(settings, activeScene)) { if (shouldPrepareCarrierlessAodNotificationTransition(settings, activeScene)) {
prepareCarrierlessAodNotificationTransition(root); prepareCarrierlessAodNotificationTransition(root);
@@ -848,12 +1064,14 @@ final class StockLayoutCanvasController {
if (activeScene.isLockscreen() if (activeScene.isLockscreen()
&& activeScene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS && activeScene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS
&& isNotificationShadeWindowRoot(root)) { && isNotificationShadeWindowRoot(root)) {
applyLockscreenCardsNotificationRowFilterInTreeIfNeeded( boolean applied = applyLockscreenCardsNotificationRowFilterInTreeIfNeeded(
root, root,
settings, settings,
activeScene, activeScene,
true); true);
if (!applied && lockscreenCardsNotificationRowFilter.hasHiddenRows()) {
lockscreenCardsNotificationRowFilter.suppressHiddenRows(); lockscreenCardsNotificationRowFilter.suppressHiddenRows();
}
} else if (activeScene.isUnlocked() && isNotificationShadeWindowRoot(root)) { } else if (activeScene.isUnlocked() && isNotificationShadeWindowRoot(root)) {
lockscreenCardsNotificationRowFilter.restoreAll(); lockscreenCardsNotificationRowFilter.restoreAll();
} else if (activeScene.isAod() } else if (activeScene.isAod()
@@ -862,6 +1080,98 @@ final class StockLayoutCanvasController {
} }
} }
private Float reflectedExpansion(Object target) {
for (String method : List.of(
"getExpandedFraction",
"getExpansionFraction",
"getPanelExpansion",
"getShadeExpansion")) {
Float value = floatValue(ReflectionSupport.invokeMethod(target, method));
if (value != null) {
return value;
}
}
for (String field : List.of(
"mExpandedFraction",
"mExpansionFraction",
"mPanelExpansionFraction",
"mShadeExpansion")) {
Float value = floatValue(ReflectionSupport.getFieldValue(target, field));
if (value != null) {
return value;
}
}
Float height = heightValue(ReflectionSupport.invokeMethod(target, "getExpandedHeight"));
if (height == null) {
height = heightValue(ReflectionSupport.getFieldValue(target, "mExpandedHeight"));
}
if (height != null && target instanceof View view && view.getHeight() > 0) {
return Math.min(1f, Math.max(0f, height / view.getHeight()));
}
return null;
}
private Float reflectedFraction(Object target) {
for (String method : List.of(
"getFraction",
"getExpandedFraction",
"getExpansionFraction",
"getPanelExpansion",
"getShadeExpansion")) {
Float value = fractionValue(ReflectionSupport.invokeMethod(target, method));
if (value != null) {
return value;
}
}
for (String field : List.of(
"fraction",
"expandedFraction",
"expansionFraction",
"panelExpansionFraction",
"shadeExpansion")) {
Float value = fractionValue(ReflectionSupport.getFieldValue(target, field));
if (value != null) {
return value;
}
}
return null;
}
private Float floatValue(Object value) {
return fractionValue(value);
}
private Float fractionValue(Object value) {
if (value instanceof Float floatValue) {
return fraction(floatValue);
}
if (value instanceof Double doubleValue) {
return fraction(doubleValue.floatValue());
}
return null;
}
private Float heightValue(Object value) {
if (value instanceof Number number) {
float floatValue = number.floatValue();
if (Float.isNaN(floatValue) || Float.isInfinite(floatValue) || floatValue < 0f) {
return null;
}
return floatValue;
}
return null;
}
private Float fraction(float value) {
if (Float.isNaN(value) || Float.isInfinite(value)) {
return null;
}
if (value < 0f || value > 1f) {
return null;
}
return value;
}
private void applyBeforeDrawInternal(View root) { private void applyBeforeDrawInternal(View root) {
if (root == null) { if (root == null) {
return; return;
@@ -894,11 +1204,13 @@ final class StockLayoutCanvasController {
&& activeScene.isLockscreen() && activeScene.isLockscreen()
&& activeScene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS && activeScene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS
&& canContainLockedStatusBarIconSurfaces(root)) { && canContainLockedStatusBarIconSurfaces(root)) {
if (isNotificationShadeWindowRoot(root)) {
applyLockscreenCardsNotificationRowFilterInTreeIfNeeded( applyLockscreenCardsNotificationRowFilterInTreeIfNeeded(
root, root,
settings, settings,
activeScene, activeScene,
isNotificationShadeWindowRoot(root)); true);
}
renderLockscreenCardsNotificationStripIfNeeded(root, settings, activeScene); renderLockscreenCardsNotificationStripIfNeeded(root, settings, activeScene);
} else if (activeScene != null } else if (activeScene != null
&& activeScene.isAod() && activeScene.isAod()
@@ -943,10 +1255,29 @@ final class StockLayoutCanvasController {
if (root != null) { if (root != null) {
dirtyUnlockedLayoutRoots.add(root); dirtyUnlockedLayoutRoots.add(root);
} }
View current = sourceView;
while (current != null) {
if (isUnlockedStatusBarRoot(current)) {
dirtyUnlockedLayoutRoots.add(current);
}
Object parent = current.getParent();
current = parent instanceof View ? (View) parent : null;
}
} }
private void markStatusChipLifecycleDirtyIfNeeded(View view) { private void requestUnlockedLayoutRefreshFromSource(View sourceView) {
markStatusChipLifecycleDirtyIfNeeded(view, null); View root = unlockedStatusBarRootFor(sourceView);
if (root != null) {
requestUnlockedLayoutRefresh(root);
}
View current = sourceView;
while (current != null) {
if (current != root && isUnlockedStatusBarRoot(current)) {
requestUnlockedLayoutRefresh(current);
}
Object parent = current.getParent();
current = parent instanceof View ? (View) parent : null;
}
} }
private void markStatusChipLifecycleDirtyIfNeeded(View view, View fallbackRoot) { private void markStatusChipLifecycleDirtyIfNeeded(View view, View fallbackRoot) {
@@ -1189,6 +1520,18 @@ final class StockLayoutCanvasController {
} }
} }
private void requestUnlockedLayoutRefreshForAllRoots() {
ArrayList<View> roots = new ArrayList<>(rootGeometries.keySet());
for (View root : new ArrayList<>(unlockedHostsByRoot.keySet())) {
if (!roots.contains(root)) {
roots.add(root);
}
}
for (View root : roots) {
requestUnlockedLayoutRefresh(root);
}
}
private void scheduleSceneRefresh(SceneKey previous, SceneKey current) { private void scheduleSceneRefresh(SceneKey previous, SceneKey current) {
if (previous == null || current == null || previous.equals(current)) { if (previous == null || current == null || previous.equals(current)) {
return; return;
@@ -1436,7 +1779,7 @@ final class StockLayoutCanvasController {
return; return;
} }
UnlockedHosts unlockedHosts = updateUnlockedOwnedHosts(root, activeScene); UnlockedHosts unlockedHosts = updateUnlockedOwnedHosts(root, activeScene);
RenderResult renderResult = new RenderResult(false, false); RenderResult renderResult = new RenderResult(false, false, false);
if (unlockedHosts != null if (unlockedHosts != null
&& (unlockedScene && (unlockedScene
|| activeScene != null && activeScene.isLockscreen() || activeScene != null && activeScene.isLockscreen()
@@ -1456,6 +1799,7 @@ final class StockLayoutCanvasController {
unlockedHosts.statusHost, unlockedHosts.statusHost,
unlockedHosts.notificationHost, unlockedHosts.notificationHost,
activeScene, activeScene,
rootDirty,
lockedCarrierTextSource()); lockedCarrierTextSource());
boolean shouldShowUnlockedHosts = unlockedScene || aodScene || renderResult.shouldOwnLockscreen(); boolean shouldShowUnlockedHosts = unlockedScene || aodScene || renderResult.shouldOwnLockscreen();
ownedIconHostManager.setUnlockedHostsVisible(root, shouldShowUnlockedHosts); ownedIconHostManager.setUnlockedHostsVisible(root, shouldShowUnlockedHosts);
@@ -1532,9 +1876,35 @@ final class StockLayoutCanvasController {
} else { } else {
removeDebugOverlay(root); removeDebugOverlay(root);
} }
if (isLayoutOffCleanupNoOp(root)) {
return;
}
cleanupLayoutOffRoot(root, activeScene); cleanupLayoutOffRoot(root, activeScene);
} }
private boolean isLayoutOffCleanupNoOp(View root) {
return hiddenViewStates.isEmpty()
&& trackedStatusChipSources.isEmpty()
&& trackedUnlockedStockSurfaces.isEmpty()
&& trackedLockedStatusBarIconSurfaces.isEmpty()
&& !lockscreenCardsNotificationRowFilter.hasHiddenRows()
&& !unlockedHostsByRoot.containsKey(root)
&& !hasDirectOwnedLayoutHost(root);
}
private boolean hasDirectOwnedLayoutHost(View root) {
if (!(root instanceof ViewGroup group)) {
return false;
}
return findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST) != null
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_AOD_CARDS_NOTIFICATION_HOST) != null;
}
private void applyDebugOverlay( private void applyDebugOverlay(
View root, View root,
boolean layoutEnabled, boolean layoutEnabled,
@@ -2113,7 +2483,8 @@ final class StockLayoutCanvasController {
private boolean shouldSuppressTrackedStatusChipVisibility(View view, int visibility) { private boolean shouldSuppressTrackedStatusChipVisibility(View view, int visibility) {
return visibility != View.VISIBLE return visibility != View.VISIBLE
&& isTrackedStatusChipWriteTarget(view) && isTrackedStatusChipWriteTarget(view)
&& hasVisibleStatusChipContent(view); && hasVisibleStatusChipContent(view)
&& !isCallStatusChip(view);
} }
private boolean isTrackedStatusChipWriteTarget(View view) { private boolean isTrackedStatusChipWriteTarget(View view) {
@@ -2528,6 +2899,43 @@ final class StockLayoutCanvasController {
return false; return false;
} }
private boolean isCallStatusChip(View source) {
if (source == null) {
return false;
}
ArrayDeque<View> queue = new ArrayDeque<>();
queue.add(source);
int scanned = 0;
while (!queue.isEmpty() && scanned++ < 48) {
View view = queue.removeFirst();
String className = view.getClass().getName().toLowerCase(Locale.ROOT);
String idName = ViewIdNames.idName(view).toLowerCase(Locale.ROOT);
if (className.contains("call") || idName.contains("call")) {
return true;
}
if (containsCallToken(view.getContentDescription())) {
return true;
}
if (view instanceof TextView textView && containsCallToken(textView.getText())) {
return true;
}
if (view instanceof ViewGroup childGroup) {
for (int i = 0; i < childGroup.getChildCount(); i++) {
queue.addLast(childGroup.getChildAt(i));
}
}
}
return false;
}
private boolean containsCallToken(CharSequence value) {
if (value == null || value.length() == 0) {
return false;
}
String text = value.toString().toLowerCase(Locale.ROOT);
return text.contains("call") || text.contains("phone");
}
private boolean isStatusChipCandidate(View view) { private boolean isStatusChipCandidate(View view) {
String className = view.getClass().getName().toLowerCase(Locale.ROOT); String className = view.getClass().getName().toLowerCase(Locale.ROOT);
String idName = ViewIdNames.idName(view).toLowerCase(Locale.ROOT); String idName = ViewIdNames.idName(view).toLowerCase(Locale.ROOT);
@@ -2798,16 +3206,7 @@ final class StockLayoutCanvasController {
LockscreenCardsNotificationIconSourceStore.clearAodSources(container); LockscreenCardsNotificationIconSourceStore.clearAodSources(container);
return; return;
} }
boolean changed = false; boolean changed = refreshAodNotificationSources(container);
ArrayList<String> packages = alignedAodIconPackages(container.getContext());
if (!packages.isEmpty()) {
changed |= LockscreenCardsNotificationIconSourceStore.putPackages(container, packages);
}
boolean prepared = prepareAodNotificationIconSources(container);
changed |= prepared;
changed |= LockscreenCardsNotificationIconSourceStore.putAodDrawables(
container,
latestAodIconImageViews);
knownAodNotificationContainers.add(container); knownAodNotificationContainers.add(container);
if (changed) { if (changed) {
View root = container.getRootView(); View root = container.getRootView();
@@ -2827,16 +3226,7 @@ final class StockLayoutCanvasController {
LockscreenCardsNotificationIconSourceStore.clearAodSources(container); LockscreenCardsNotificationIconSourceStore.clearAodSources(container);
continue; continue;
} }
ArrayList<String> packages = alignedAodIconPackages(container.getContext()); boolean changed = refreshAodNotificationSources(container);
boolean changed = false;
if (!packages.isEmpty()) {
changed |= LockscreenCardsNotificationIconSourceStore.putPackages(container, packages);
}
boolean prepared = prepareAodNotificationIconSources(container);
changed |= prepared;
changed |= LockscreenCardsNotificationIconSourceStore.putAodDrawables(
container,
latestAodIconImageViews);
if (changed) { if (changed) {
View root = container.getRootView(); View root = container.getRootView();
invalidateAodNotificationRoot(root); invalidateAodNotificationRoot(root);
@@ -2844,10 +3234,24 @@ final class StockLayoutCanvasController {
} }
} }
private boolean refreshAodNotificationSources(ViewGroup container) {
ArrayList<String> packages = alignedAodIconPackages(container.getContext());
if (packages.isEmpty() && isAodDotScene()) {
packages = aodNotificationPackages();
}
boolean changed = false;
if (!packages.isEmpty()) {
changed |= LockscreenCardsNotificationIconSourceStore.putPackages(container, packages);
}
changed |= prepareAodNotificationIconSources(container);
changed |= LockscreenCardsNotificationIconSourceStore.putAodDrawables(
container,
latestAodIconImageViews);
return changed;
}
private boolean prepareAodNotificationIconSources(ViewGroup container) { private boolean prepareAodNotificationIconSources(ViewGroup container) {
if (container == null if (container == null || latestAodIconImageViews.isEmpty()) {
|| latestAodIconImageViews == null
|| latestAodIconImageViews.isEmpty()) {
return false; return false;
} }
boolean invoked = false; boolean invoked = false;
@@ -2867,9 +3271,25 @@ final class StockLayoutCanvasController {
return invoked; return invoked;
} }
private boolean isAodDotScene() {
SceneKey scene = runtimeContext.getModeStateRepository().getActiveScene();
return scene != null
&& scene.isAod()
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT;
}
private ArrayList<String> aodNotificationPackages() {
ArrayList<String> result = new ArrayList<>();
for (StatusBarNotification sbn : latestAodNotifications) {
if (sbn != null && AppIconRules.isValidPackageName(sbn.getPackageName())) {
result.add(sbn.getPackageName());
}
}
return result;
}
private ArrayList<String> alignedAodIconPackages(Context context) { private ArrayList<String> alignedAodIconPackages(Context context) {
int imageCount = latestAodIconImageViews != null ? latestAodIconImageViews.size() : 0; if (latestAodIconImageViews.isEmpty()) {
if (imageCount <= 0) {
return new ArrayList<>(); return new ArrayList<>();
} }
ArrayList<String> aligned = alignAodPackagesByDrawable(context); ArrayList<String> aligned = alignAodPackagesByDrawable(context);
@@ -2882,9 +3302,7 @@ final class StockLayoutCanvasController {
private ArrayList<String> alignAodPackagesByDrawable(Context context) { private ArrayList<String> alignAodPackagesByDrawable(Context context) {
ArrayList<String> aligned = new ArrayList<>(); ArrayList<String> aligned = new ArrayList<>();
if (context == null if (context == null
|| latestAodIconImageViews == null
|| latestAodIconImageViews.isEmpty() || latestAodIconImageViews.isEmpty()
|| latestAodNotifications == null
|| latestAodNotifications.isEmpty()) { || latestAodNotifications.isEmpty()) {
return aligned; return aligned;
} }
@@ -2989,6 +3407,20 @@ final class StockLayoutCanvasController {
dirtyUnlockedLayoutRoots.add(root); dirtyUnlockedLayoutRoots.add(root);
} }
private void markKnownAodNotificationRootsDirty() {
for (ViewGroup container : knownAodNotificationContainers) {
if (container == null || !container.isAttachedToWindow()) {
continue;
}
View root = container.getRootView();
if (root != null) {
dirtyUnlockedLayoutRoots.add(root);
root.requestLayout();
root.invalidate();
}
}
}
private void markAodLayoutDirty(View view) { private void markAodLayoutDirty(View view) {
if (view == null || !view.isAttachedToWindow()) { if (view == null || !view.isAttachedToWindow()) {
return; return;
@@ -3151,19 +3583,19 @@ final class StockLayoutCanvasController {
return true; return true;
} }
private void restoreAllHiddenViews() { private void restoreAllHiddenViews(View root, SceneKey activeScene) {
ArrayDeque<View> views = new ArrayDeque<>(hiddenViewStates.keySet()); ArrayDeque<View> views = new ArrayDeque<>(hiddenViewStates.keySet());
while (!views.isEmpty()) { while (!views.isEmpty()) {
View view = views.removeFirst(); View view = views.removeFirst();
if (forgetInactiveTrackedStatusChip(view)) { if (forgetInactiveTrackedStatusChip(view)) {
continue; continue;
} }
if (shouldDeferLayoutOffRestore(root, activeScene, view)) {
keepViewHidden(view);
continue;
}
restoreView(view); restoreView(view);
} }
trackedStatusChipSources.clear();
trackedLockedStatusBarIconSurfaces.clear();
trackedUnlockedStockSurfaces.clear();
aodPluginVisualAlphaByView.clear();
} }
private boolean forgetInactiveTrackedStatusChip(View view) { private boolean forgetInactiveTrackedStatusChip(View view) {
@@ -3176,16 +3608,16 @@ final class StockLayoutCanvasController {
hiddenViewStates.remove(view); hiddenViewStates.remove(view);
trackedStatusChipSources.remove(view); trackedStatusChipSources.remove(view);
trackedUnlockedStockSurfaces.remove(view); trackedUnlockedStockSurfaces.remove(view);
statusChipLifecycleLayoutSignatureByView.remove(view);
return true; return true;
} }
private void cleanupLayoutOffRoot(View root, SceneKey activeScene) { private void cleanupLayoutOffRoot(View root, SceneKey activeScene) {
lockscreenCardsNotificationRowFilter.restoreAll(); lockscreenCardsNotificationRowFilter.restoreAll();
if (!hiddenViewStates.isEmpty()) { if (!hiddenViewStates.isEmpty()) {
restoreAllHiddenViews(); restoreAllHiddenViews(root, activeScene);
} }
restoreLayoutOffStockSurfaces(root, activeScene); clearTrackedStatusChipState();
trackedStatusChipSources.clear();
trackedLockedStatusBarIconSurfaces.clear(); trackedLockedStatusBarIconSurfaces.clear();
trackedUnlockedStockSurfaces.clear(); trackedUnlockedStockSurfaces.clear();
confirmedAodPluginViews.clear(); confirmedAodPluginViews.clear();
@@ -3219,63 +3651,38 @@ final class StockLayoutCanvasController {
ownedIconHostManager.removeOwnedHosts(root); ownedIconHostManager.removeOwnedHosts(root);
} }
private void restoreLayoutOffStockSurfaces(View root, SceneKey activeScene) { private boolean shouldDeferLayoutOffRestore(
if (root == null || !isViewThread(root)) { View root,
return; SceneKey activeScene,
} View view
boolean unlockedScene = activeScene == null || activeScene.isUnlocked();
walkTree(root, view -> {
if (!isLayoutOffRecoverableStockSurface(view)) {
return;
}
String idName = ViewIdNames.idName(view);
int beforeVisibility = view.getVisibility();
float beforeAlpha = view.getAlpha();
restoreView(view);
if (!unlockedScene && LAYOUT_OFF_UNLOCKED_ONLY_IDS.contains(idName)) {
if (view.getAlpha() != 0f) {
view.setAlpha(0f);
}
if (view.getVisibility() != View.INVISIBLE) {
view.setVisibility(View.INVISIBLE);
}
return;
}
if (unlockedScene && view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
if (shouldPreserveUnlockedStockAlpha(idName, beforeVisibility, beforeAlpha)) {
if (view.getAlpha() != beforeAlpha) {
view.setAlpha(beforeAlpha);
}
return;
}
if (unlockedScene && view.getAlpha() <= 0f) {
view.setAlpha(1f);
}
});
}
private boolean shouldPreserveUnlockedStockAlpha(
String idName,
int beforeVisibility,
float beforeAlpha
) { ) {
if (!"notification_icon_area_inner".equals(idName)) { return shouldKeepUnlockedShadeShelfOwnedByCustomLayout(root, activeScene, view);
return false;
}
return beforeVisibility == View.VISIBLE && beforeAlpha < 1f;
} }
private boolean isLayoutOffRecoverableStockSurface(View view) { private void keepViewHidden(View view) {
if (view == null || ownedIconHostManager.isOwnedHost(view)) { hideView(view, false);
}
private boolean shouldKeepUnlockedShadeShelfOwnedByCustomLayout(
View root,
SceneKey activeScene,
View view
) {
if (root == null
|| activeScene == null
|| !activeScene.isUnlocked()
|| !isDescendantOfNotificationShadeWindow(view)) {
return false; return false;
} }
String idName = ViewIdNames.idName(view); return (isCardsNotificationIconSurface(view) || isCardsNotificationShelfBackgroundSurface(view))
String className = view.getClass().getName(); && hasAncestorClass(view, "NotificationShelf");
return LAYOUT_OFF_UNLOCKED_ONLY_IDS.contains(idName) }
|| LAYOUT_OFF_EXTRA_RECOVERABLE_IDS.contains(idName)
|| containsAny(className, LAYOUT_OFF_RECOVERABLE_CLASS_SUBSTRINGS); private void clearTrackedStatusChipState() {
trackedStatusChipSources.clear();
statusChipContentSignatureByRoot.clear();
statusChipLayoutSignatureByRoot.clear();
statusChipLifecycleLayoutSignatureByView.clear();
} }
private static boolean containsAny(String value, Set<String> tokens) { private static boolean containsAny(String value, Set<String> tokens) {
@@ -3395,11 +3802,20 @@ final class StockLayoutCanvasController {
generation = 31 * generation + latestAodNotifications.size(); generation = 31 * generation + latestAodNotifications.size();
Bounds sourceBounds = LockscreenCardsNotificationIconSourceStore Bounds sourceBounds = LockscreenCardsNotificationIconSourceStore
.sourceContainerBoundsForRoot(root); .sourceContainerBoundsForRoot(root);
boolean hiddenSource = LockscreenCardsNotificationIconSourceStore
.sourceContainerHasHiddenAncestorForRoot(root);
if (hiddenSource) {
// Samsung hides the cards icon source during the clock/date handoff.
// Keep our mirror hidden too instead of following its transient translation.
setHostAlpha(host, 0f);
return;
}
generation = 31 * generation + (sourceBounds != null ? sourceBounds.signature() : 0); generation = 31 * generation + (sourceBounds != null ? sourceBounds.signature() : 0);
Integer previous = aodCardsNotificationRenderGenerationByRoot.get(root); Integer previous = aodCardsNotificationRenderGenerationByRoot.get(root);
boolean dirty = dirtyUnlockedLayoutRoots.contains(root);
boolean shouldRender = previous == null boolean shouldRender = previous == null
|| previous != generation || previous != generation
|| dirtyUnlockedLayoutRoots.contains(root) || dirty
|| hostGroup.getChildCount() <= 0; || hostGroup.getChildCount() <= 0;
if (shouldRender) { if (shouldRender) {
aodCardsNotificationRenderGenerationByRoot.put(root, generation); aodCardsNotificationRenderGenerationByRoot.put(root, generation);
@@ -3421,7 +3837,7 @@ final class StockLayoutCanvasController {
lockscreenCardsNotificationRowFilter.apply(stack, allowAfterKeyguardUnlock); lockscreenCardsNotificationRowFilter.apply(stack, allowAfterKeyguardUnlock);
} }
private void applyLockscreenCardsNotificationRowFilterInTreeIfNeeded( private boolean applyLockscreenCardsNotificationRowFilterInTreeIfNeeded(
View root, View root,
SbtSettings settings, SbtSettings settings,
SceneKey activeScene, SceneKey activeScene,
@@ -3429,9 +3845,10 @@ final class StockLayoutCanvasController {
int signature = lockscreenCardsRowFilterSignature(root, settings, activeScene); int signature = lockscreenCardsRowFilterSignature(root, settings, activeScene);
Integer previous = lockscreenCardsRowFilterSignatures.put(root, signature); Integer previous = lockscreenCardsRowFilterSignatures.put(root, signature);
if (previous != null && previous == signature) { if (previous != null && previous == signature) {
return; return false;
} }
applyLockscreenCardsNotificationRowFilterInTree(root, allowAfterKeyguardUnlock); applyLockscreenCardsNotificationRowFilterInTree(root, allowAfterKeyguardUnlock);
return true;
} }
private int lockscreenCardsRowFilterSignature( private int lockscreenCardsRowFilterSignature(
@@ -3620,11 +4037,13 @@ final class StockLayoutCanvasController {
} }
NotificationDisplayStyle notificationStyle = NotificationDisplayStyle notificationStyle =
SystemNotificationDisplayStyleDetector.read(context); SystemNotificationDisplayStyleDetector.read(context);
if (isAodRoot(root) || (isKeyguardLocked(context) && !isInteractive(context))) { boolean keyguardLocked = isKeyguardLocked(context);
boolean interactive = isInteractive(context);
if (isAodRoot(root) || (keyguardLocked && !interactive)) {
runtimeContext.getModeStateRepository().setAod(notificationStyle); runtimeContext.getModeStateRepository().setAod(notificationStyle);
return; return;
} }
if (isKeyguardLocked(context)) { if (keyguardLocked) {
runtimeContext.getModeStateRepository().setLockscreen(notificationStyle); runtimeContext.getModeStateRepository().setLockscreen(notificationStyle);
return; return;
} }
@@ -798,7 +798,7 @@ public final class PackedStatusBarLayoutSolver {
} }
} }
public static void collisionTree(ArrayList<LayoutItem> items) { private static void collisionTree(ArrayList<LayoutItem> items) {
for (LayoutItem item : items) { for (LayoutItem item : items) {
for (Box box : item.boxes) { for (Box box : item.boxes) {
box.collisionLeft.clear(); box.collisionLeft.clear();
@@ -1165,11 +1165,6 @@ public final class PackedStatusBarLayoutSolver {
return oldWidth - width(); return oldWidth - width();
} }
public void setPoolRemaining(int remaining) {
poolRemaining = Math.max(0, remaining);
recomputeIconState();
}
public void setPoolIcons(ArrayList<Integer> widths, int startIndex) { public void setPoolIcons(ArrayList<Integer> widths, int startIndex) {
widthLimit = Math.min(currentWidthLimit(), width()); widthLimit = Math.min(currentWidthLimit(), width());
poolIconWidths = widths != null ? new ArrayList<>(widths) : new ArrayList<>(); poolIconWidths = widths != null ? new ArrayList<>(widths) : new ArrayList<>();
@@ -1,668 +1,9 @@
package se.ajpanton.statusbartweak.runtime.layoutsolver; package se.ajpanton.statusbartweak.runtime.layoutsolver;
import java.util.ArrayList;
import java.util.Collections;
public final class StatusBarLayoutSolver { public final class StatusBarLayoutSolver {
private static final int MIDDLE_COLLISION_MARGIN_PX = 2;
private StatusBarLayoutSolver() { private StatusBarLayoutSolver() {
} }
public static <T extends LayoutBand> ArrayList<T> bandsForPosition(
ArrayList<T> bands,
LayoutPosition position,
ArrayList<LayoutItemKind> itemOrder
) {
ArrayList<T> result = new ArrayList<>();
for (LayoutItemKind kind : itemOrder) {
for (T band : bands) {
if (band.kind == kind
&& band.position == position
&& band.splitRegion == SplitRegion.NONE) {
result.add(band);
}
}
}
return result;
}
public static <T extends LayoutBand> ArrayList<T> middleBandsForPlacement(
ArrayList<T> bands,
ArrayList<LayoutItemKind> itemOrder,
AnchorSide side
) {
ArrayList<T> result = new ArrayList<>();
SplitRegion sideRegion = side == AnchorSide.LEFT ? SplitRegion.LEFT : SplitRegion.RIGHT;
for (T band : bands) {
if (band.splitRegion == sideRegion) {
result.add(band);
}
}
result.addAll(bandsForPosition(bands, LayoutPosition.MIDDLE, itemOrder));
return result;
}
public static <T extends LayoutBand> RegionPlan<T> planRegions(
int rootWidth,
LayoutEdges edges,
ArrayList<T> bands,
ArrayList<LayoutItemKind> itemOrder,
Bounds cutoutBounds,
int itemPadding
) {
int leftEdge = Math.max(0, Math.min(rootWidth, edges.left));
int rightEdge = Math.max(leftEdge, Math.min(rootWidth, edges.right));
Region<T> leftRegion;
Region<T> rightRegion = null;
if (cutoutBounds == null) {
leftRegion = new Region<>(leftEdge, rightEdge);
} else {
leftRegion = new Region<>(leftEdge, Math.min(cutoutBounds.left, rightEdge));
rightRegion = new Region<>(
Math.max(cutoutBounds.left + cutoutBounds.width, leftEdge),
rightEdge);
}
ArrayList<T> leftBands = bandsForPosition(bands, LayoutPosition.LEFT, itemOrder);
ArrayList<T> middleBands = bandsForPosition(bands, LayoutPosition.MIDDLE, itemOrder);
ArrayList<T> rightBands = bandsForPosition(bands, LayoutPosition.RIGHT, itemOrder);
AnchorSide middleSide = sideForMiddleRegion(rootWidth, middleBands, cutoutBounds, itemPadding);
if (rightRegion == null) {
addSplitRegionBands(bands, leftRegion, SplitRegion.LEFT);
addSplitRegionBands(bands, leftRegion, SplitRegion.RIGHT);
leftRegion.bands.addAll(leftBands);
leftRegion.bands.addAll(middleBands);
Collections.reverse(rightBands);
leftRegion.bands.addAll(rightBands);
} else {
leftRegion.bands.addAll(leftBands);
ArrayList<T> middleRegionBands = new ArrayList<>(middleBands);
Collections.reverse(middleRegionBands);
if (middleSide == AnchorSide.LEFT) {
leftRegion.bands.addAll(middleRegionBands);
}
addSplitRegionBands(bands, leftRegion, SplitRegion.LEFT);
addSplitRegionBands(bands, rightRegion, SplitRegion.RIGHT);
if (middleSide == AnchorSide.RIGHT) {
rightRegion.bands.addAll(middleRegionBands);
}
Collections.reverse(rightBands);
rightRegion.bands.addAll(rightBands);
}
ArrayList<Region<T>> regions = new ArrayList<>();
regions.add(leftRegion);
if (rightRegion != null) {
regions.add(rightRegion);
}
return new RegionPlan<>(regions, middleSide);
}
private static <T extends LayoutBand> void addSplitRegionBands(
ArrayList<T> source,
Region<T> target,
SplitRegion region
) {
if (source == null || target == null || region == SplitRegion.NONE) {
return;
}
for (T band : source) {
if (band.splitRegion == region) {
target.bands.add(band);
}
}
}
public static <T extends LayoutBand> AnchorSide sideForMiddleRegion(
int rootWidth,
ArrayList<T> middleBands,
Bounds cutoutBounds,
int itemPadding
) {
int middle = rootWidth / 2;
if (middleBands == null || middleBands.isEmpty()) {
return cutoutBounds == null || cutoutBounds.left + cutoutBounds.width / 2 < middle
? AnchorSide.RIGHT
: AnchorSide.LEFT;
}
T firstBand = middleBands.get(0);
int width = packedWidth(middleBands, itemPadding);
int cameraDistance = distanceFromMiddle(cutoutBounds, middle);
boolean centered = cutoutBounds != null
&& cutoutBounds.left <= middle + MIDDLE_COLLISION_MARGIN_PX
&& cutoutBounds.left + cutoutBounds.width >= middle - MIDDLE_COLLISION_MARGIN_PX;
if (cameraDistance < width / 2 && (centered || !firstBand.middleAutoNearestSide)) {
return firstBand.middleSide;
}
if (cutoutBounds == null || cutoutBounds.left + cutoutBounds.width / 2 < middle) {
return AnchorSide.RIGHT;
}
return AnchorSide.LEFT;
}
public static <T extends LayoutBand> Anchor anchorForMiddle(
int rootWidth,
ArrayList<T> bands,
ArrayList<PlacedBand> placedBands,
Bounds cutoutBounds,
AnchorSide side,
int itemPadding
) {
int middle = rootWidth / 2;
int width = packedWidth(bands, itemPadding);
if (coversMiddle(cutoutBounds, middle)) {
return obstacleAnchor(cutoutBounds, side, AnchorKind.WALL);
}
Bounds nearestItem = nearestPlacedBand(placedBands, middle);
int cameraDistance = distanceFromMiddle(cutoutBounds, middle);
int itemDistance = distanceFromMiddle(nearestItem, middle);
if (Math.min(cameraDistance, itemDistance) < width / 2) {
if (cameraDistance < itemDistance) {
return obstacleAnchor(cutoutBounds, side, AnchorKind.WALL);
}
return obstacleAnchor(nearestItem, side, AnchorKind.ITEM);
}
return middleAnchor(rootWidth, width, side);
}
private static Anchor obstacleAnchor(Bounds obstacle, AnchorSide side, AnchorKind kind) {
if (obstacle == null) {
return new Anchor(0, side, kind);
}
int anchorPoint = side == AnchorSide.RIGHT ? obstacle.left + obstacle.width : obstacle.left;
return new Anchor(anchorPoint, side, kind);
}
private static Anchor middleAnchor(int rootWidth, int width, AnchorSide side) {
int middle = rootWidth / 2;
if (side == AnchorSide.RIGHT) {
return new Anchor(middle - width / 2, AnchorSide.RIGHT, AnchorKind.CENTER);
}
return new Anchor(middle + width / 2, AnchorSide.LEFT, AnchorKind.CENTER);
}
public static <T extends LayoutBand> void placeStackedBands(
ArrayList<T> bands,
Anchor anchor,
ArrayList<PlacedBand> placedBands,
String sortOrder,
boolean avoidPlacedBands,
int itemPadding
) {
if (bands == null || bands.isEmpty()) {
return;
}
for (T band : bands) {
band.prepareForSide(anchor.side, sortOrder);
}
ArrayList<StackedBand<T>> stackedBands = stackBands(bands, itemPadding);
int shift = avoidPlacedBands ? middleShift(stackedBands, anchor, placedBands, itemPadding) : 0;
for (StackedBand<T> stackedBand : stackedBands) {
T band = stackedBand.band;
int wallDotSlack = anchor.kind == AnchorKind.WALL
&& stackedBand.left == 0
&& shift == 0
? band.wallDotSlack(anchor.side)
: 0;
int left = stackedLeft(stackedBand, anchor, shift, wallDotSlack, itemPadding);
band.place(left);
ArrayList<Bounds> bounds = band.placedCollisionBounds();
if (!bounds.isEmpty()) {
placedBands.add(new PlacedBand(band.kind, band.position, bounds));
}
}
}
private static <T extends LayoutBand> int middleShift(
ArrayList<StackedBand<T>> stackedBands,
Anchor anchor,
ArrayList<PlacedBand> placedBands,
int itemPadding
) {
int shift = 0;
for (StackedBand<T> stackedBand : stackedBands) {
ArrayList<Bounds> bounds = boundsForStackedBand(stackedBand, anchor, shift, itemPadding);
int leftOverstep = overstepFromPlacedBands(bounds, placedBands, LayoutPosition.LEFT, itemPadding);
if (leftOverstep > 0) {
shift += leftOverstep;
continue;
}
int rightOverstep = overstepFromPlacedBands(bounds, placedBands, LayoutPosition.RIGHT, itemPadding);
if (rightOverstep > 0) {
shift -= rightOverstep;
}
}
return shift;
}
private static <T extends LayoutBand> ArrayList<Bounds> boundsForStackedBand(
StackedBand<T> stackedBand,
Anchor anchor,
int shift,
int itemPadding
) {
ArrayList<Bounds> result = new ArrayList<>();
int left = stackedLeft(stackedBand, anchor, shift, 0, itemPadding);
for (Bounds box : stackedBand.boxes) {
result.add(new Bounds(left + box.left, box.top, box.width, box.height));
}
return result;
}
private static <T extends LayoutBand> int stackedLeft(
StackedBand<T> stackedBand,
Anchor anchor,
int shift,
int wallDotSlack,
int itemPadding
) {
T band = stackedBand.band;
int anchorGap = anchor.kind == AnchorKind.ITEM ? Math.max(0, itemPadding) : 0;
if (anchor.side == AnchorSide.RIGHT) {
return anchor.point + anchorGap + stackedBand.left + shift - wallDotSlack;
}
return anchor.point - anchorGap - stackedBand.left - band.width() + shift + wallDotSlack;
}
private static int overstepFromPlacedBands(
ArrayList<Bounds> bounds,
ArrayList<PlacedBand> placedBands,
LayoutPosition position,
int itemPadding
) {
int overstep = 0;
if (bounds == null || placedBands == null) {
return overstep;
}
for (Bounds boundsItem : bounds) {
if (boundsItem == null) {
continue;
}
for (PlacedBand placedBand : placedBands) {
if (placedBand.position != position) {
continue;
}
for (Bounds obstacle : placedBand.bounds) {
if (obstacle == null
|| !verticalRangesOverlap(
boundsItem.top,
boundsItem.height,
obstacle.top,
obstacle.height)) {
continue;
}
overstep = Math.max(overstep, horizontalOverstep(boundsItem, obstacle, position, itemPadding));
}
}
}
return overstep;
}
private static int horizontalOverstep(
Bounds item,
Bounds obstacle,
LayoutPosition obstaclePosition,
int itemPadding
) {
int gap = Math.max(0, itemPadding);
if (obstaclePosition == LayoutPosition.LEFT) {
return Math.max(0, obstacle.left + blockingWidth(obstacle) + gap - item.left);
}
if (obstaclePosition == LayoutPosition.RIGHT) {
return Math.max(0, item.left + blockingWidth(item) + gap - obstacle.left);
}
return 0;
}
public static <T extends LayoutBand> void truncateToFit(
ArrayList<T> bands,
int freeSpace,
AnchorSide middleSide,
String sortOrder,
int itemPadding
) {
int target = Math.max(0, freeSpace);
for (T band : bands) {
band.prepareForSide(truncationAnchorSide(band, middleSide), sortOrder);
}
int guard = 64;
while (packedWidthForTruncation(bands, middleSide, itemPadding) > target && guard-- > 0) {
if (shrinkToReducePackedWidth(bands, LayoutItemKind.NOTIFICATIONS, middleSide, itemPadding)) {
continue;
}
if (shrinkToReducePackedWidth(bands, LayoutItemKind.STATUS, middleSide, itemPadding)) {
continue;
}
if (clipToReducePackedWidth(bands, LayoutItemKind.CHIP, middleSide, target, itemPadding)) {
continue;
}
if (removeDotToReducePackedWidth(bands, LayoutItemKind.NOTIFICATIONS, middleSide, itemPadding)) {
continue;
}
if (removeDotToReducePackedWidth(bands, LayoutItemKind.STATUS, middleSide, itemPadding)) {
continue;
}
if (clipToReducePackedWidth(bands, LayoutItemKind.CLOCK, middleSide, target, itemPadding)) {
continue;
}
break;
}
}
private static <T extends LayoutBand> boolean shrinkToReducePackedWidth(
ArrayList<T> bands,
LayoutItemKind kind,
AnchorSide middleSide,
int itemPadding
) {
return mutateBandToReducePackedWidth(
bands,
kind,
middleSide,
itemPadding,
LayoutBand::shrinkOneIcon,
false,
true);
}
private static <T extends LayoutBand> boolean removeDotToReducePackedWidth(
ArrayList<T> bands,
LayoutItemKind kind,
AnchorSide middleSide,
int itemPadding
) {
return mutateBandToReducePackedWidth(
bands,
kind,
middleSide,
itemPadding,
LayoutBand::removeOverflowDot,
true,
false);
}
private static <T extends LayoutBand> boolean mutateBandToReducePackedWidth(
ArrayList<T> bands,
LayoutItemKind kind,
AnchorSide middleSide,
int itemPadding,
BandMutation mutation,
boolean acceptEqualWidth,
boolean acceptCreatedDot
) {
T band = findBand(bands, kind);
if (band == null) {
return false;
}
int before = packedWidthForTruncation(bands, middleSide, itemPadding);
Object state = band.captureState();
if (!mutation.apply(band)) {
return false;
}
int after = packedWidthForTruncation(bands, middleSide, itemPadding);
if (after < before
|| (acceptEqualWidth && after == before)
|| (acceptCreatedDot && band.createdOverflowDotSince(state))) {
return true;
}
band.restoreState(state);
return false;
}
private static <T extends LayoutBand> boolean clipToReducePackedWidth(
ArrayList<T> bands,
LayoutItemKind kind,
AnchorSide middleSide,
int target,
int itemPadding
) {
T band = findBand(bands, kind);
if (band == null || !band.canClipContinuously()) {
return false;
}
int before = packedWidthForTruncation(bands, middleSide, itemPadding);
int amount = Math.max(1, before - target);
if (!band.clipContinuous(truncationAnchorSide(band, middleSide), amount)) {
return false;
}
return packedWidthForTruncation(bands, middleSide, itemPadding) <= before;
}
public static <T extends LayoutBand> int packedWidth(ArrayList<T> bands) {
return packedWidth(bands, 0);
}
public static <T extends LayoutBand> int packedWidth(ArrayList<T> bands, int itemPadding) {
return stackBounds(stackBands(bands, itemPadding)).width;
}
private static <T extends LayoutBand> int packedWidthForTruncation(
ArrayList<T> bands,
AnchorSide middleSide,
int itemPadding
) {
ArrayList<StackedBand<T>> stackedBands = stackBands(bands, itemPadding);
Bounds bounds = stackBounds(stackedBands);
int width = bounds.width;
if (width <= 0 || stackedBands.isEmpty()) {
return width;
}
int leftEdge = bounds.left;
int rightEdge = bounds.left + bounds.width;
Integer leftSlack = null;
Integer rightSlack = null;
for (StackedBand<T> stackedBand : stackedBands) {
T band = stackedBand.band;
Bounds bandBounds = shiftedBounds(stackedBand.boxes, stackedBand.left);
int bandLeft = bandBounds != null ? bandBounds.left : stackedBand.left;
int bandRight = bandBounds != null ? bandBounds.left + bandBounds.width : bandLeft;
if (bandLeft == leftEdge) {
int slack = band.wallDotSlack(AnchorSide.RIGHT);
leftSlack = leftSlack == null ? slack : Math.min(leftSlack, slack);
}
if (bandRight == rightEdge) {
int slack = band.wallDotSlack(AnchorSide.LEFT);
rightSlack = rightSlack == null ? slack : Math.min(rightSlack, slack);
}
}
return Math.max(0, width - (leftSlack != null ? leftSlack : 0) - (rightSlack != null ? rightSlack : 0));
}
private static AnchorSide truncationAnchorSide(LayoutBand band, AnchorSide middleSide) {
if (band.splitRegion == SplitRegion.LEFT) {
return AnchorSide.LEFT;
}
if (band.splitRegion == SplitRegion.RIGHT) {
return AnchorSide.RIGHT;
}
if (band.position == LayoutPosition.LEFT) {
return AnchorSide.RIGHT;
}
if (band.position == LayoutPosition.RIGHT) {
return AnchorSide.LEFT;
}
return middleSide;
}
private static <T extends LayoutBand> ArrayList<StackedBand<T>> stackBands(
ArrayList<T> bands,
int itemPadding
) {
ArrayList<StackedBand<T>> stackedBands = new ArrayList<>();
if (bands == null) {
return stackedBands;
}
int gap = Math.max(0, itemPadding);
for (T band : bands) {
int left = 0;
ArrayList<Bounds> boxes = band.collisionBoxes();
for (StackedBand<T> stackedBand : stackedBands) {
for (Bounds box : boxes) {
for (Bounds placedBox : stackedBand.boxes) {
if (verticalRangesOverlap(box.top, box.height, placedBox.top, placedBox.height)) {
left = Math.max(
left,
stackedBand.left + placedBox.left + blockingWidth(placedBox) + gap - box.left);
}
}
}
}
stackedBands.add(new StackedBand<>(band, left, boxes));
}
return stackedBands;
}
private static <T extends LayoutBand> Bounds stackBounds(ArrayList<StackedBand<T>> stackedBands) {
Bounds bounds = new Bounds(0, 0, 0, 0);
if (stackedBands == null || stackedBands.isEmpty()) {
return bounds;
}
Bounds union = null;
for (StackedBand<T> stackedBand : stackedBands) {
Bounds bandBounds = shiftedBounds(stackedBand.boxes, stackedBand.left);
if (bandBounds != null) {
union = union == null ? bandBounds : union.union(bandBounds);
}
}
return union != null ? union : bounds;
}
private static Bounds shiftedBounds(ArrayList<Bounds> boxes, int left) {
Bounds union = null;
if (boxes == null) {
return null;
}
for (Bounds box : boxes) {
Bounds shifted = new Bounds(left + box.left, box.top, blockingWidth(box), box.height);
union = union == null ? shifted : union.union(shifted);
}
return union;
}
private static boolean verticalRangesOverlap(int topA, int heightA, int topB, int heightB) {
return topA < topB + heightB && topB < topA + heightA;
}
private static int blockingWidth(Bounds bounds) {
return bounds != null && bounds.height > 0 ? Math.max(1, bounds.width) : 0;
}
private static <T extends LayoutBand> T findBand(ArrayList<T> bands, LayoutItemKind kind) {
for (T band : bands) {
if (band.kind == kind) {
return band;
}
}
return null;
}
private static Bounds nearestPlacedBand(ArrayList<PlacedBand> placedBands, int middle) {
Bounds nearest = null;
int nearestDistance = Integer.MAX_VALUE;
for (PlacedBand placedBand : placedBands) {
for (Bounds bounds : placedBand.bounds) {
int distance = distanceFromMiddle(bounds, middle);
if (distance < nearestDistance) {
nearest = bounds;
nearestDistance = distance;
}
}
}
return nearest;
}
public static int distanceFromMiddle(Bounds bounds, int middle) {
if (bounds == null) {
return Integer.MAX_VALUE;
}
if (bounds.left <= middle && bounds.left + bounds.width >= middle) {
return 0;
}
return Math.min(Math.abs(middle - bounds.left), Math.abs(middle - (bounds.left + bounds.width)));
}
public static boolean coversMiddle(Bounds bounds, int middle) {
return bounds != null
&& bounds.left <= middle + MIDDLE_COLLISION_MARGIN_PX
&& bounds.left + bounds.width >= middle - MIDDLE_COLLISION_MARGIN_PX;
}
public abstract static class LayoutBand {
public final LayoutItemKind kind;
public final LayoutPosition position;
public final boolean middleAutoNearestSide;
public final AnchorSide middleSide;
public final SplitRegion splitRegion;
protected LayoutBand(
LayoutItemKind kind,
LayoutPosition position,
boolean middleAutoNearestSide,
AnchorSide middleSide,
SplitRegion splitRegion
) {
this.kind = kind;
this.position = position;
this.middleAutoNearestSide = middleAutoNearestSide;
this.middleSide = middleSide;
this.splitRegion = splitRegion != null ? splitRegion : SplitRegion.NONE;
}
protected abstract void prepareForSide(AnchorSide side, String sortOrder);
protected abstract int width();
protected abstract ArrayList<Bounds> collisionBoxes();
protected abstract void place(int left);
protected abstract ArrayList<Bounds> placedCollisionBounds();
protected int wallDotSlack(AnchorSide side) {
return 0;
}
protected boolean shrinkOneIcon() {
return false;
}
protected boolean removeOverflowDot() {
return false;
}
protected Object captureState() {
return null;
}
protected void restoreState(Object state) {
}
protected boolean createdOverflowDotSince(Object state) {
return false;
}
protected boolean canClipContinuously() {
return false;
}
protected boolean clipContinuous(AnchorSide wallSide, int amountPx) {
return false;
}
}
private interface BandMutation {
boolean apply(LayoutBand band);
}
private record StackedBand<T extends LayoutBand>(
T band,
int left,
ArrayList<Bounds> boxes
) {
}
public enum LayoutItemKind { public enum LayoutItemKind {
CARRIER, CARRIER,
CLOCK, CLOCK,
@@ -682,21 +23,12 @@ public final class StatusBarLayoutSolver {
RIGHT RIGHT
} }
public enum AnchorKind {
WALL,
ITEM,
CENTER
}
public enum SplitRegion { public enum SplitRegion {
NONE, NONE,
LEFT, LEFT,
RIGHT RIGHT
} }
public record Anchor(int point, AnchorSide side, AnchorKind kind) {
}
public static final class Bounds { public static final class Bounds {
public final int left; public final int left;
public final int top; public final int top;
@@ -726,36 +58,24 @@ public final class StatusBarLayoutSolver {
result = 31 * result + height; result = 31 * result + height;
return result; return result;
} }
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Bounds other)) {
return false;
}
return left == other.left
&& top == other.top
&& width == other.width
&& height == other.height;
} }
public record PlacedBand( @Override
LayoutItemKind kind, public int hashCode() {
LayoutPosition position, return signature();
ArrayList<Bounds> bounds
) {
}
public record RegionPlan<T extends LayoutBand>(
ArrayList<Region<T>> regions,
AnchorSide middleSide
) {
}
public record LayoutEdges(int left, int right) {
}
public static final class Region<T extends LayoutBand> {
public final int left;
public final int right;
public final ArrayList<T> bands = new ArrayList<>();
Region(int left, int right) {
this.left = left;
this.right = Math.max(left, right);
}
public int width() {
return Math.max(0, right - left);
} }
} }
} }
@@ -2,15 +2,9 @@ package se.ajpanton.statusbartweak.runtime.mode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects;
/** /**
* Central source of truth for the current scene. * Central source of truth for the current scene.
*
* This is intentionally small at the reset stage: it only tracks the active
* scene and whether the custom layout runtime should currently output anything.
* Hook-driven updates can be wired in later without changing the rest of the
* runtime API.
*/ */
public final class ModeStateRepository { public final class ModeStateRepository {
private SceneKey activeScene = SceneKey.unlocked(); private SceneKey activeScene = SceneKey.unlocked();
@@ -19,6 +13,7 @@ public final class ModeStateRepository {
private boolean layoutEnabled; private boolean layoutEnabled;
private final List<LayoutEnabledListener> layoutEnabledListeners = new ArrayList<>(); private final List<LayoutEnabledListener> layoutEnabledListeners = new ArrayList<>();
private final List<SceneListener> sceneListeners = new ArrayList<>(); private final List<SceneListener> sceneListeners = new ArrayList<>();
private final List<SystemUiStatusBarStateListener> systemUiStatusBarStateListeners = new ArrayList<>();
public synchronized SceneKey getActiveScene() { public synchronized SceneKey getActiveScene() {
return activeScene; return activeScene;
@@ -68,10 +63,6 @@ public final class ModeStateRepository {
setActiveScene(SceneKey.aod(requireDisplayStyle(style))); setActiveScene(SceneKey.aod(requireDisplayStyle(style)));
} }
public void setScene(SceneKey sceneKey) {
setActiveScene(Objects.requireNonNull(sceneKey, "sceneKey"));
}
public void setSystemUiStatusBarState( public void setSystemUiStatusBarState(
int state, int state,
boolean dozing, boolean dozing,
@@ -84,11 +75,23 @@ public final class ModeStateRepository {
SceneKey scene = dozing SceneKey scene = dozing
? SceneKey.aod(style) ? SceneKey.aod(style)
: state == 0 ? SceneKey.unlocked() : SceneKey.lockscreen(style); : state == 0 ? SceneKey.unlocked() : SceneKey.lockscreen(style);
boolean changed;
int previousState;
boolean previousKnown;
synchronized (this) { synchronized (this) {
previousKnown = systemUiStatusBarStateKnown;
previousState = systemUiStatusBarState;
changed = !systemUiStatusBarStateKnown || systemUiStatusBarState != state;
systemUiStatusBarStateKnown = true; systemUiStatusBarStateKnown = true;
systemUiStatusBarState = state; systemUiStatusBarState = state;
} }
setActiveScene(scene); setActiveScene(scene);
if (changed) {
notifySystemUiStatusBarStateListeners(
previousKnown ? previousState : -1,
state,
dozing);
}
} }
public synchronized void addSceneListener(SceneListener listener) { public synchronized void addSceneListener(SceneListener listener) {
@@ -97,6 +100,14 @@ public final class ModeStateRepository {
} }
} }
public synchronized void addSystemUiStatusBarStateListener(
SystemUiStatusBarStateListener listener
) {
if (listener != null && !systemUiStatusBarStateListeners.contains(listener)) {
systemUiStatusBarStateListeners.add(listener);
}
}
private void setActiveScene(SceneKey scene) { private void setActiveScene(SceneKey scene) {
SceneKey previous; SceneKey previous;
List<SceneListener> listeners; List<SceneListener> listeners;
@@ -108,19 +119,22 @@ public final class ModeStateRepository {
activeScene = scene; activeScene = scene;
listeners = new ArrayList<>(sceneListeners); listeners = new ArrayList<>(sceneListeners);
} }
notifySceneChanged(previous, scene, listeners); for (SceneListener listener : listeners) {
listener.onSceneChanged(previous, scene);
}
} }
private void notifySceneChanged( private void notifySystemUiStatusBarStateListeners(
SceneKey previous, int previousState,
SceneKey current, int currentState,
List<SceneListener> listeners boolean dozing
) { ) {
if (listeners == null || listeners.isEmpty()) { List<SystemUiStatusBarStateListener> listeners;
return; synchronized (this) {
listeners = new ArrayList<>(systemUiStatusBarStateListeners);
} }
for (SceneListener listener : listeners) { for (SystemUiStatusBarStateListener listener : listeners) {
listener.onSceneChanged(previous, current); listener.onSystemUiStatusBarStateChanged(previousState, currentState, dozing);
} }
} }
@@ -138,4 +152,8 @@ public final class ModeStateRepository {
public interface SceneListener { public interface SceneListener {
void onSceneChanged(SceneKey previous, SceneKey current); void onSceneChanged(SceneKey previous, SceneKey current);
} }
public interface SystemUiStatusBarStateListener {
void onSystemUiStatusBarStateChanged(int previousState, int currentState, boolean dozing);
}
} }
@@ -0,0 +1,68 @@
package se.ajpanton.statusbartweak.runtime.notifications;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public final class NotificationActiveKeyStore {
private static final HashSet<String> ACTIVE_KEYS = new HashSet<>();
private static int generation;
private NotificationActiveKeyStore() {
}
public static synchronized boolean replace(Collection<String> keys) {
HashSet<String> normalized = new HashSet<>();
if (keys != null) {
for (String key : keys) {
addKey(normalized, key);
}
}
if (ACTIVE_KEYS.equals(normalized)) {
return false;
}
ACTIVE_KEYS.clear();
ACTIVE_KEYS.addAll(normalized);
generation++;
return true;
}
public static synchronized boolean hasSnapshot() {
return !ACTIVE_KEYS.isEmpty();
}
public static synchronized boolean isActive(String key) {
String normalized = normalizeKey(key);
return normalized != null && ACTIVE_KEYS.contains(normalized);
}
public static synchronized int generation() {
return generation;
}
public static synchronized Set<String> snapshot() {
return new HashSet<>(ACTIVE_KEYS);
}
private static void addKey(HashSet<String> out, String key) {
String normalized = normalizeKey(key);
if (normalized != null) {
out.add(normalized);
}
}
private static String normalizeKey(String key) {
if (key == null) {
return null;
}
String normalized = key.trim();
if (normalized.isEmpty()) {
return null;
}
int identitySuffix = normalized.indexOf('@');
if (identitySuffix >= 0) {
normalized = normalized.substring(0, identitySuffix);
}
return normalized.isEmpty() ? null : normalized;
}
}
@@ -0,0 +1,137 @@
package se.ajpanton.statusbartweak.runtime.notifications;
import android.app.Notification;
import android.os.Bundle;
import android.service.notification.StatusBarNotification;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import se.ajpanton.statusbartweak.runtime.NotificationKeyReflection;
import se.ajpanton.statusbartweak.shell.settings.AppIconRules;
public final class NotificationUnreadTracker {
private static final HashMap<String, State> STATE_BY_KEY = new HashMap<>();
private static final HashMap<String, Long> UPDATED_BY_PACKAGE = new HashMap<>();
private static long lastSeenMs;
private static int generation;
private NotificationUnreadTracker() {
}
public static synchronized boolean markSeen() {
long now = System.currentTimeMillis();
if (now <= lastSeenMs) {
return false;
}
lastSeenMs = now;
generation++;
return true;
}
public static synchronized boolean record(StatusBarNotification sbn) {
if (sbn == null || !AppIconRules.isValidPackageName(sbn.getPackageName())) {
return false;
}
String key = sbn.getKey();
if (key == null || key.isEmpty()) {
return false;
}
int signature = signature(sbn);
State previous = STATE_BY_KEY.get(key);
if (previous != null && previous.signature == signature) {
return false;
}
long updateTime = previous == null ? notificationTime(sbn) : System.currentTimeMillis();
State state = new State(sbn.getPackageName(), signature, updateTime);
STATE_BY_KEY.put(key, state);
Long packageTime = UPDATED_BY_PACKAGE.get(state.packageName);
if (packageTime == null || updateTime > packageTime) {
UPDATED_BY_PACKAGE.put(state.packageName, updateTime);
}
generation++;
return updateTime > lastSeenMs;
}
public static synchronized boolean retainActiveKeys(Set<String> activeKeys) {
if (activeKeys == null) {
return false;
}
boolean changed = STATE_BY_KEY.keySet().removeIf(key -> !activeKeys.contains(key));
if (changed) {
rebuildPackageTimes();
generation++;
}
return changed;
}
public static synchronized int generation() {
return generation;
}
public static synchronized boolean isUnread(String key) {
if (key == null || key.isEmpty()) {
return false;
}
State state = STATE_BY_KEY.get(key);
if (state != null) {
return state.updatedMs > lastSeenMs;
}
String packageName = NotificationKeyReflection.packageFromNotificationKey(key);
Long packageTime = packageName != null ? UPDATED_BY_PACKAGE.get(packageName) : null;
return packageTime != null && packageTime > lastSeenMs;
}
private static long notificationTime(StatusBarNotification sbn) {
long result = sbn.getPostTime();
Notification notification = sbn.getNotification();
if (notification != null && notification.when > result) {
result = notification.when;
}
return result > 0L ? result : System.currentTimeMillis();
}
private static int signature(StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
Bundle extras = notification != null ? notification.extras : null;
return Objects.hash(
sbn.getKey(),
sbn.getPostTime(),
notification != null ? notification.when : 0L,
notification != null ? notification.number : 0,
notification != null ? notification.flags : 0,
notification != null ? notification.category : null,
textExtra(extras, Notification.EXTRA_TITLE),
textExtra(extras, Notification.EXTRA_TEXT),
textExtra(extras, Notification.EXTRA_BIG_TEXT),
textExtra(extras, Notification.EXTRA_SUB_TEXT));
}
private static String textExtra(Bundle extras, String key) {
CharSequence value = extras != null ? extras.getCharSequence(key) : null;
return value != null ? value.toString() : null;
}
private static void rebuildPackageTimes() {
UPDATED_BY_PACKAGE.clear();
for (State state : STATE_BY_KEY.values()) {
Long previous = UPDATED_BY_PACKAGE.get(state.packageName);
if (previous == null || state.updatedMs > previous) {
UPDATED_BY_PACKAGE.put(state.packageName, state.updatedMs);
}
}
}
private static final class State {
final String packageName;
final int signature;
final long updatedMs;
State(String packageName, int signature, long updatedMs) {
this.packageName = packageName;
this.signature = signature;
this.updatedMs = updatedMs;
}
}
}
@@ -18,7 +18,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import se.ajpanton.statusbartweak.R; import se.ajpanton.statusbartweak.R;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle; import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
import se.ajpanton.statusbartweak.runtime.mode.SceneKey; import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings; import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
@@ -209,9 +209,9 @@ public final class DebugBoundsOverlayController {
Bounds notificationBounds = aodNotificationBounds(root, scene); Bounds notificationBounds = aodNotificationBounds(root, scene);
Bounds statusBounds = liveAodStatusIconsBounds(root); Bounds statusBounds = liveAodStatusIconsBounds(root);
if (!isUsableAodAnchor(root, statusBounds)) { if (!isUsableAodAnchor(root, statusBounds)) {
statusBounds = overlayBounds(AodStatusbarSourceStore.statusBoundsForRoot( statusBounds = AodStatusbarSourceStore.statusBoundsForRoot(
root, root,
notificationContainer)); notificationContainer);
} }
boolean hasNotification = isUsableAodAnchor(root, notificationBounds); boolean hasNotification = isUsableAodAnchor(root, notificationBounds);
boolean hasStatus = isUsableAodAnchor(root, statusBounds); boolean hasStatus = isUsableAodAnchor(root, statusBounds);
@@ -238,8 +238,7 @@ public final class DebugBoundsOverlayController {
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) { && scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) {
return null; return null;
} }
return overlayBounds( return LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForAodIconsRoot(root);
LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForAodIconsRoot(root));
} }
private ViewGroup aodNotificationContainer(View root, SceneKey scene) { private ViewGroup aodNotificationContainer(View root, SceneKey scene) {
@@ -266,16 +265,8 @@ public final class DebugBoundsOverlayController {
return bounds != null ? bounds.signature() : 0; return bounds != null ? bounds.signature() : 0;
} }
private Bounds overlayBounds(StatusBarLayoutSolver.Bounds bounds) {
if (bounds == null) {
return null;
}
return new Bounds(bounds.left, bounds.top, bounds.width, bounds.height);
}
private Bounds liveAodStatusIconsBounds(View root) { private Bounds liveAodStatusIconsBounds(View root) {
StatusBarLayoutSolver.Bounds bounds = AodLiveStatusbarSource.boundsForRoot(root); return AodLiveStatusbarSource.boundsForRoot(root);
return bounds != null ? new Bounds(bounds.left, bounds.top, bounds.width, bounds.height) : null;
} }
private void addCutoutSpecs(View root, ArrayList<OverlaySpec> specs) { private void addCutoutSpecs(View root, ArrayList<OverlaySpec> specs) {
@@ -352,8 +343,8 @@ public final class DebugBoundsOverlayController {
} }
ArrayList<Bounds> out = new ArrayList<>(); ArrayList<Bounds> out = new ArrayList<>();
for (Object value : values) { for (Object value : values) {
if (value instanceof StatusBarLayoutSolver.Bounds bounds) { if (value instanceof Bounds bounds) {
out.add(new Bounds(bounds.left, bounds.top, bounds.width, bounds.height)); out.add(bounds);
} }
} }
return out; return out;
@@ -606,25 +597,6 @@ public final class DebugBoundsOverlayController {
} }
} }
private record Bounds(int left, int top, int width, int height) {
Bounds union(Bounds other) {
int right = Math.max(left + width, other.left + other.width);
int bottom = Math.max(top + height, other.top + other.height);
int newLeft = Math.min(left, other.left);
int newTop = Math.min(top, other.top);
return new Bounds(newLeft, newTop, right - newLeft, bottom - newTop);
}
int signature() {
int result = 17;
result = 31 * result + left;
result = 31 * result + top;
result = 31 * result + width;
result = 31 * result + height;
return result;
}
}
private static final class OverlayView extends View { private static final class OverlayView extends View {
private final Paint paint = new Paint(); private final Paint paint = new Paint();
private ArrayList<OverlaySpec> specs = new ArrayList<>(); private ArrayList<OverlaySpec> specs = new ArrayList<>();
@@ -25,6 +25,7 @@ public final class LockscreenCardsNotificationIconSourceStore {
new WeakHashMap<>(); new WeakHashMap<>();
private static final WeakHashMap<ViewGroup, ArrayList<View>> AOD_DRAWABLES_BY_CONTAINER = private static final WeakHashMap<ViewGroup, ArrayList<View>> AOD_DRAWABLES_BY_CONTAINER =
new WeakHashMap<>(); new WeakHashMap<>();
private static final ArrayList<String> AOD_NOTIFICATION_PACKAGES = new ArrayList<>();
private static final int VIRTUAL_ICON_SIZE_PX = 39; private static final int VIRTUAL_ICON_SIZE_PX = 39;
private LockscreenCardsNotificationIconSourceStore() { private LockscreenCardsNotificationIconSourceStore() {
@@ -113,6 +114,7 @@ public final class LockscreenCardsNotificationIconSourceStore {
public static void clearAodSources() { public static void clearAodSources() {
PACKAGES_BY_CONTAINER.clear(); PACKAGES_BY_CONTAINER.clear();
AOD_DRAWABLES_BY_CONTAINER.clear(); AOD_DRAWABLES_BY_CONTAINER.clear();
AOD_NOTIFICATION_PACKAGES.clear();
} }
public static void clearAodSources(ViewGroup container) { public static void clearAodSources(ViewGroup container) {
@@ -123,6 +125,18 @@ public final class LockscreenCardsNotificationIconSourceStore {
AOD_DRAWABLES_BY_CONTAINER.remove(container); AOD_DRAWABLES_BY_CONTAINER.remove(container);
} }
public static void putAodNotificationPackages(ArrayList<String> packages) {
AOD_NOTIFICATION_PACKAGES.clear();
if (packages == null || packages.isEmpty()) {
return;
}
for (String pkg : packages) {
if (AppIconRules.isValidPackageName(pkg) && !AOD_NOTIFICATION_PACKAGES.contains(pkg)) {
AOD_NOTIFICATION_PACKAGES.add(pkg);
}
}
}
private static boolean sameViews(ArrayList<View> previous, ArrayList<View> current) { private static boolean sameViews(ArrayList<View> previous, ArrayList<View> current) {
if (previous == current) { if (previous == current) {
return true; return true;
@@ -252,6 +266,25 @@ public final class LockscreenCardsNotificationIconSourceStore {
return result; return result;
} }
static ArrayList<SnapshotSource> snapshotAodNotificationPackageSources(View root) {
ArrayList<SnapshotSource> result = new ArrayList<>();
if (AOD_NOTIFICATION_PACKAGES.isEmpty()) {
return result;
}
Bounds bounds = sourceContainerBoundsForAodIconsRoot(root);
int top = bounds != null ? bounds.top : 0;
int size = VIRTUAL_ICON_SIZE_PX;
for (int i = 0; i < AOD_NOTIFICATION_PACKAGES.size(); i++) {
String pkg = AOD_NOTIFICATION_PACKAGES.get(i);
result.add(new SnapshotSource(
null,
SnapshotMode.APP_ICON,
pkg + "@aodUnread" + i,
new Bounds(0, top, size, size)));
}
return result;
}
static ViewGroup sourceContainerForRoot(View root) { static ViewGroup sourceContainerForRoot(View root) {
ViewGroup container = sourceContainerForRoot(root, AOD_DRAWABLES_BY_CONTAINER.keySet()); ViewGroup container = sourceContainerForRoot(root, AOD_DRAWABLES_BY_CONTAINER.keySet());
if (container != null) { if (container != null) {
@@ -284,6 +317,22 @@ public final class LockscreenCardsNotificationIconSourceStore {
return bounds; return bounds;
} }
public static boolean sourceContainerHasHiddenAncestorForRoot(View root) {
ViewGroup container = sourceContainerForRoot(root);
if (container == null) {
return false;
}
View current = container;
while (current != null && current != root) {
if (current.getVisibility() != View.VISIBLE) {
return true;
}
Object parent = current.getParent();
current = parent instanceof View ? (View) parent : null;
}
return current != root;
}
public static Bounds sourceContainerBoundsForAodIconsRoot(View root) { public static Bounds sourceContainerBoundsForAodIconsRoot(View root) {
ViewGroup container = sourceContainerForAodIconsRoot(root); ViewGroup container = sourceContainerForAodIconsRoot(root);
Bounds bounds = sourceBoundsRelativeTo(root, container); Bounds bounds = sourceBoundsRelativeTo(root, container);
@@ -294,7 +343,11 @@ public final class LockscreenCardsNotificationIconSourceStore {
} }
private static Bounds sourceBoundsRelativeTo(View root, ViewGroup container) { private static Bounds sourceBoundsRelativeTo(View root, ViewGroup container) {
Bounds bounds = container != null ? ViewGeometry.boundsRelativeTo(root, container) : null; Bounds bounds = rawSourceBoundsRelativeTo(root, container);
return normalizeSourceBounds(container, bounds);
}
private static Bounds normalizeSourceBounds(ViewGroup container, Bounds bounds) {
if (bounds == null || isZeroSizeDotContainer(container, bounds)) { if (bounds == null || isZeroSizeDotContainer(container, bounds)) {
return bounds; return bounds;
} }
@@ -308,6 +361,10 @@ public final class LockscreenCardsNotificationIconSourceStore {
return new Bounds(bounds.left, top, bounds.width, VIRTUAL_ICON_SIZE_PX); return new Bounds(bounds.left, top, bounds.width, VIRTUAL_ICON_SIZE_PX);
} }
private static Bounds rawSourceBoundsRelativeTo(View root, ViewGroup container) {
return container != null ? ViewGeometry.boundsRelativeTo(root, container) : null;
}
private static boolean hasAodSources(ViewGroup container) { private static boolean hasAodSources(ViewGroup container) {
return container != null return container != null
&& (AOD_DRAWABLES_BY_CONTAINER.containsKey(container) && (AOD_DRAWABLES_BY_CONTAINER.containsKey(container)
@@ -460,15 +460,6 @@ final class LayoutPlan {
final ArrayList<SnapshotPlacement> notificationPlacements; final ArrayList<SnapshotPlacement> notificationPlacements;
final ClockPlacement carrierPlacement; final ClockPlacement carrierPlacement;
LayoutPlan(
ClockPlacement clockPlacement,
ArrayList<SnapshotPlacement> chipPlacements,
ArrayList<SnapshotPlacement> statusPlacements,
ArrayList<SnapshotPlacement> notificationPlacements
) {
this(clockPlacement, chipPlacements, statusPlacements, notificationPlacements, null);
}
LayoutPlan( LayoutPlan(
ClockPlacement clockPlacement, ClockPlacement clockPlacement,
ArrayList<SnapshotPlacement> chipPlacements, ArrayList<SnapshotPlacement> chipPlacements,
@@ -65,13 +65,14 @@ public final class UnlockedIconSnapshotRenderController {
ViewGroup statusHost, ViewGroup statusHost,
ViewGroup notificationHost, ViewGroup notificationHost,
SceneKey scene, SceneKey scene,
boolean forceStockRefresh,
TextView externalCarrierView TextView externalCarrierView
) { ) {
if (scene == null if (scene == null
|| (!scene.isUnlocked() && !scene.isLockscreen() && !scene.isAod()) || (!scene.isUnlocked() && !scene.isLockscreen() && !scene.isAod())
|| !root.isAttachedToWindow()) { || !root.isAttachedToWindow()) {
clearAll(); clearAll();
return new RenderResult(true, true); return new RenderResult(true, true, true);
} }
SbtSettings settings = RuntimeSettingsCache.get(root.getContext()); SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
layoutHostToRoot(root, clockHost); layoutHostToRoot(root, clockHost);
@@ -139,7 +140,7 @@ public final class UnlockedIconSnapshotRenderController {
lastLayoutPlanByRoot.put(root, updatedPlan); lastLayoutPlanByRoot.put(root, updatedPlan);
lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry); lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry);
clockRenderer.render(clockHost, updatedClock); clockRenderer.render(clockHost, updatedClock);
return new RenderResult(false, false); return new RenderResult(false, false, false);
} }
} }
currentClockLayout = buildClockLayout(root, anchors, settings); currentClockLayout = buildClockLayout(root, anchors, settings);
@@ -166,16 +167,16 @@ public final class UnlockedIconSnapshotRenderController {
LayoutPlan updatedPlan = previousPlan.withClockPlacement(updatedClock); LayoutPlan updatedPlan = previousPlan.withClockPlacement(updatedClock);
lastLayoutPlanByRoot.put(root, updatedPlan); lastLayoutPlanByRoot.put(root, updatedPlan);
clockRenderer.render(clockHost, updatedClock); clockRenderer.render(clockHost, updatedClock);
return new RenderResult(false, false); return new RenderResult(false, false, false);
} }
} }
CollectedIcons collectedIcons = previousIcons; CollectedIcons collectedIcons = previousIcons;
if (forceChipRefresh && collectedIcons != null) { if (forceStockRefresh || sceneChanged || stockSourcesChanged || collectedIcons == null) {
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
lastCollectedIconsByRoot.put(root, collectedIcons);
} else if (sceneChanged || stockSourcesChanged || collectedIcons == null) {
collectedIcons = sourceCollector.collect(root, anchors, scene); collectedIcons = sourceCollector.collect(root, anchors, scene);
lastCollectedIconsByRoot.put(root, collectedIcons); lastCollectedIconsByRoot.put(root, collectedIcons);
} else if (forceChipRefresh && collectedIcons != null) {
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
lastCollectedIconsByRoot.put(root, collectedIcons);
} else if (chipSourcesChanged) { } else if (chipSourcesChanged) {
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons); collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
lastCollectedIconsByRoot.put(root, collectedIcons); lastCollectedIconsByRoot.put(root, collectedIcons);
@@ -993,10 +994,6 @@ public final class UnlockedIconSnapshotRenderController {
boolean chipSourcesChanged, boolean chipSourcesChanged,
boolean shouldOwnLockscreen boolean shouldOwnLockscreen
) { ) {
public RenderResult(boolean layoutChanged, boolean stockSourcesChanged) {
this(layoutChanged, stockSourcesChanged, stockSourcesChanged, true);
}
public RenderResult(boolean layoutChanged, boolean stockSourcesChanged, boolean chipSourcesChanged) { public RenderResult(boolean layoutChanged, boolean stockSourcesChanged, boolean chipSourcesChanged) {
this(layoutChanged, stockSourcesChanged, chipSourcesChanged, true); this(layoutChanged, stockSourcesChanged, chipSourcesChanged, true);
} }
@@ -6,21 +6,21 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Locale; import java.util.Locale;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.AnchorSide; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.AnchorSide;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutItemKind; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutItemKind;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutPosition; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutPosition;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.SplitRegion; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.SplitRegion;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand { final class UnlockedLayoutBand {
final LayoutItemKind kind;
final LayoutPosition position;
final AnchorSide middleSide;
final SplitRegion splitRegion;
final ViewGroup host; final ViewGroup host;
final SnapshotRenderer renderer; final SnapshotRenderer renderer;
final ArrayList<SnapshotPlacement> rawPlacements; final ArrayList<SnapshotPlacement> rawPlacements;
final boolean showDotIfTruncated;
final boolean forceOverflowDotOnly; final boolean forceOverflowDotOnly;
final Bounds reservedBounds;
final ClockLayout clockLayout; final ClockLayout clockLayout;
ArrayList<SnapshotPlacement> placements; ArrayList<SnapshotPlacement> placements;
@@ -37,21 +37,19 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
SnapshotRenderer renderer, SnapshotRenderer renderer,
ArrayList<SnapshotPlacement> rawPlacements, ArrayList<SnapshotPlacement> rawPlacements,
LayoutPosition position, LayoutPosition position,
boolean middleAutoNearestSide,
AnchorSide middleSide, AnchorSide middleSide,
boolean showDotIfTruncated,
boolean forceOverflowDotOnly, boolean forceOverflowDotOnly,
Bounds reservedBounds,
ClockLayout clockLayout, ClockLayout clockLayout,
SplitRegion splitRegion SplitRegion splitRegion
) { ) {
super(kind, position, middleAutoNearestSide, middleSide, splitRegion); this.kind = kind;
this.position = position;
this.middleSide = middleSide;
this.splitRegion = splitRegion != null ? splitRegion : SplitRegion.NONE;
this.host = host; this.host = host;
this.renderer = renderer; this.renderer = renderer;
this.rawPlacements = rawPlacements; this.rawPlacements = rawPlacements;
this.showDotIfTruncated = showDotIfTruncated;
this.forceOverflowDotOnly = forceOverflowDotOnly; this.forceOverflowDotOnly = forceOverflowDotOnly;
this.reservedBounds = reservedBounds;
this.clockLayout = clockLayout; this.clockLayout = clockLayout;
} }
@@ -59,7 +57,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
ViewGroup host, ViewGroup host,
ClockLayout clockLayout, ClockLayout clockLayout,
LayoutPosition position, LayoutPosition position,
SbtSettings settings AnchorSide middleSide
) { ) {
return new UnlockedLayoutBand( return new UnlockedLayoutBand(
LayoutItemKind.CLOCK, LayoutItemKind.CLOCK,
@@ -67,11 +65,8 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
null, null,
null, null,
position, position,
settings.clockMiddleAutoNearestSide, middleSide,
sideFor(settings.clockMiddleCutoutSide),
false, false,
false,
null,
clockLayout, clockLayout,
SplitRegion.NONE); SplitRegion.NONE);
} }
@@ -80,7 +75,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
ViewGroup host, ViewGroup host,
ClockLayout clockLayout, ClockLayout clockLayout,
SplitRegion splitRegion, SplitRegion splitRegion,
SbtSettings settings AnchorSide middleSide
) { ) {
return new UnlockedLayoutBand( return new UnlockedLayoutBand(
LayoutItemKind.CLOCK, LayoutItemKind.CLOCK,
@@ -88,11 +83,8 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
null, null,
null, null,
LayoutPosition.MIDDLE, LayoutPosition.MIDDLE,
settings.clockMiddleAutoNearestSide, middleSide,
sideFor(settings.clockMiddleCutoutSide),
false, false,
false,
null,
clockLayout, clockLayout,
splitRegion); splitRegion);
} }
@@ -101,7 +93,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
ViewGroup host, ViewGroup host,
ClockLayout carrierLayout, ClockLayout carrierLayout,
LayoutPosition position, LayoutPosition position,
boolean middleAutoNearestSide,
AnchorSide middleSide AnchorSide middleSide
) { ) {
return new UnlockedLayoutBand( return new UnlockedLayoutBand(
@@ -110,11 +101,8 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
null, null,
null, null,
position, position,
middleAutoNearestSide,
middleSide, middleSide,
false, false,
false,
null,
carrierLayout, carrierLayout,
SplitRegion.NONE); SplitRegion.NONE);
} }
@@ -125,9 +113,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
SnapshotRenderer renderer, SnapshotRenderer renderer,
ArrayList<SnapshotPlacement> rawPlacements, ArrayList<SnapshotPlacement> rawPlacements,
LayoutPosition position, LayoutPosition position,
boolean middleAutoNearestSide, AnchorSide middleSide
AnchorSide middleSide,
boolean showDotIfTruncated
) { ) {
return new UnlockedLayoutBand( return new UnlockedLayoutBand(
kind, kind,
@@ -135,12 +121,9 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
renderer, renderer,
rawPlacements, rawPlacements,
position, position,
middleAutoNearestSide,
middleSide, middleSide,
showDotIfTruncated,
false, false,
null, null,
null,
SplitRegion.NONE); SplitRegion.NONE);
} }
@@ -156,7 +139,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
SnapshotRenderer renderer, SnapshotRenderer renderer,
ArrayList<SnapshotPlacement> rawPlacements, ArrayList<SnapshotPlacement> rawPlacements,
LayoutPosition position, LayoutPosition position,
boolean middleAutoNearestSide,
AnchorSide middleSide AnchorSide middleSide
) { ) {
return new UnlockedLayoutBand( return new UnlockedLayoutBand(
@@ -165,20 +147,16 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
renderer, renderer,
rawPlacements, rawPlacements,
position, position,
middleAutoNearestSide,
middleSide, middleSide,
true, true,
true,
null,
null, null,
SplitRegion.NONE); SplitRegion.NONE);
} }
@Override void prepareForSide(AnchorSide side, String sortOrder) {
protected void prepareForSide(AnchorSide side, String sortOrder) {
if (isTextKind()) { if (isTextKind()) {
placements = null; placements = null;
placedBounds = clockLayout != null ? clockLayout.bounds() : reservedBounds; placedBounds = clockLayout != null ? clockLayout.bounds() : null;
return; return;
} }
placements = new ArrayList<>(activePlacements()); placements = new ArrayList<>(activePlacements());
@@ -189,8 +167,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
placedBounds = null; placedBounds = null;
} }
@Override int width() {
protected int width() {
return Math.max(0, naturalWidth() - clipStartPx - clipEndPx); return Math.max(0, naturalWidth() - clipStartPx - clipEndPx);
} }
@@ -199,19 +176,17 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
if (clockLayout != null) { if (clockLayout != null) {
return clockLayout.width(); return clockLayout.width();
} }
return reservedBounds != null ? reservedBounds.width : 0; return 0;
} }
return sumWidths(activePlacements()); return sumWidths(activePlacements());
} }
@Override boolean canClipContinuously() {
protected boolean canClipContinuously() {
return (kind == LayoutItemKind.CHIP || isTextKind()) return (kind == LayoutItemKind.CHIP || isTextKind())
&& naturalWidth() > clipStartPx + clipEndPx; && naturalWidth() > clipStartPx + clipEndPx;
} }
@Override boolean clipContinuous(AnchorSide wallSide, int amountPx) {
protected boolean clipContinuous(AnchorSide wallSide, int amountPx) {
int remaining = naturalWidth() - clipStartPx - clipEndPx; int remaining = naturalWidth() - clipStartPx - clipEndPx;
if (amountPx <= 0 || remaining <= 0 || !canClipContinuously()) { if (amountPx <= 0 || remaining <= 0 || !canClipContinuously()) {
return false; return false;
@@ -261,23 +236,12 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
} }
} }
@Override
protected int wallDotSlack(AnchorSide side) {
SnapshotPlacement placement = wallPlacement(side);
if (placement == null || !placement.overflowDot) {
return 0;
}
int collisionWidth = relativeCollisionBounds(placement).width;
int dotWidth = overflowDotVisualWidth(placement);
return Math.max(0, (collisionWidth - dotWidth) / 2);
}
int height() { int height() {
if (isTextKind()) { if (isTextKind()) {
if (clockLayout != null) { if (clockLayout != null) {
return clockLayout.height(); return clockLayout.height();
} }
return reservedBounds != null ? reservedBounds.height : 0; return 0;
} }
int height = 0; int height = 0;
for (SnapshotPlacement placement : activePlacements()) { for (SnapshotPlacement placement : activePlacements()) {
@@ -291,7 +255,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
if (clockLayout != null) { if (clockLayout != null) {
return clockLayout.top(); return clockLayout.top();
} }
return reservedBounds != null ? reservedBounds.top : 0; return 0;
} }
int top = Integer.MAX_VALUE; int top = Integer.MAX_VALUE;
for (SnapshotPlacement placement : activePlacements()) { for (SnapshotPlacement placement : activePlacements()) {
@@ -300,41 +264,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return top == Integer.MAX_VALUE ? 0 : top; return top == Integer.MAX_VALUE ? 0 : top;
} }
@Override
protected boolean shrinkOneIcon() {
if (kind == LayoutItemKind.NOTIFICATIONS) {
return shrinkIcon(false);
}
if (kind == LayoutItemKind.STATUS) {
return shrinkIcon(true);
}
return false;
}
@Override
protected boolean removeOverflowDot() {
if (placements == null || placements.isEmpty()) {
return false;
}
ArrayList<SnapshotPlacement> withoutDot = new ArrayList<>();
boolean removed = false;
for (SnapshotPlacement placement : placements) {
if (placement.overflowDot) {
removed = true;
} else {
withoutDot.add(placement);
}
}
if (!removed) {
return false;
}
if (withoutDot.isEmpty()) {
withoutDot.add(emptyIconContainerPlacement());
}
placements = withoutDot;
return true;
}
private void replaceOverflowDot(int width, int height) { private void replaceOverflowDot(int width, int height) {
if (placements == null) { if (placements == null) {
placements = new ArrayList<>(); placements = new ArrayList<>();
@@ -354,29 +283,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
placements = withoutDot; placements = withoutDot;
} }
@Override void place(int left) {
protected Object captureState() {
return new LayoutBandState(placements == null, new ArrayList<>(activePlacements()));
}
@Override
protected void restoreState(Object state) {
if (!(state instanceof LayoutBandState bandState)) {
return;
}
placements = bandState.placementsWereNull ? null : new ArrayList<>(bandState.placements);
}
@Override
protected boolean createdOverflowDotSince(Object state) {
if (!(state instanceof LayoutBandState bandState)) {
return hasOverflowDot(activePlacements());
}
return !hasOverflowDot(bandState.placements) && hasOverflowDot(activePlacements());
}
@Override
protected void place(int left) {
if (isTextKind()) { if (isTextKind()) {
placedBounds = clockLayout != null placedBounds = clockLayout != null
? clockLayout.place(left) ? clockLayout.place(left)
@@ -441,8 +348,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return union; return union;
} }
@Override ArrayList<Bounds> collisionBoxes() {
protected ArrayList<Bounds> collisionBoxes() {
ArrayList<Bounds> boxes = new ArrayList<>(); ArrayList<Bounds> boxes = new ArrayList<>();
if (isTextKind()) { if (isTextKind()) {
if (clockLayout != null) { if (clockLayout != null) {
@@ -455,8 +361,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
boxes.add(new Bounds(left - clipStartPx, box.top, right - left, box.height)); boxes.add(new Bounds(left - clipStartPx, box.top, right - left, box.height));
} }
} }
} else if (reservedBounds != null) {
boxes.add(new Bounds(0, reservedBounds.top, width(), reservedBounds.height));
} }
return boxes; return boxes;
} }
@@ -486,47 +390,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return solverBoxes; return solverBoxes;
} }
@Override
protected ArrayList<Bounds> placedCollisionBounds() {
ArrayList<Bounds> boxes = new ArrayList<>();
int left = isTextKind() && placedBounds != null
? placedBounds.left
: 0;
for (Bounds box : collisionBoxes()) {
boxes.add(new Bounds(left + box.left, box.top, box.width, box.height));
}
if (kind != LayoutItemKind.CLOCK && placedBounds != null) {
boxes.clear();
boxes.add(placedBounds);
}
return boxes;
}
private SnapshotPlacement wallPlacement(AnchorSide side) {
if (isTextKind()) {
return null;
}
ArrayList<SnapshotPlacement> icons = activePlacements();
if (icons.isEmpty()) {
return null;
}
boolean wallAtStart = side == AnchorSide.RIGHT;
int index;
if (wallAtStart) {
index = reverseForPlacement ? icons.size() - 1 : 0;
} else {
index = reverseForPlacement ? 0 : icons.size() - 1;
}
return icons.get(index);
}
private int overflowDotVisualWidth(SnapshotPlacement placement) {
Bounds bounds = placement.bounds;
int base = Math.max(1, Math.min(bounds.width, bounds.height));
int radius = Math.max(1, Math.round(base * 0.125f));
return Math.min(bounds.width, radius * 2);
}
private Bounds collisionBounds(SnapshotPlacement placement) { private Bounds collisionBounds(SnapshotPlacement placement) {
Bounds relative = relativeCollisionBounds(placement); Bounds relative = relativeCollisionBounds(placement);
Bounds bounds = placement.bounds; Bounds bounds = placement.bounds;
@@ -547,38 +410,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return new Bounds(0, 0, bounds.width, bounds.height); return new Bounds(0, 0, bounds.width, bounds.height);
} }
private boolean shrinkIcon(boolean fromStart) {
ArrayList<SnapshotPlacement> icons = new ArrayList<>(activePlacements());
int removeIndex = nonDotIndex(icons, fromStart);
if (removeIndex < 0) {
return false;
}
boolean hadDot = hasOverflowDot(icons);
icons.remove(removeIndex);
if (showDotIfTruncated && !hadDot) {
SnapshotPlacement dot = dotPlacement(dotWidth(icons), dotHeight(icons), rowTop(icons));
if (fromStart) {
icons.add(0, dot);
} else {
icons.add(dot);
}
}
placements = icons;
return true;
}
private int nonDotIndex(ArrayList<SnapshotPlacement> icons, boolean fromStart) {
int start = fromStart ? 0 : icons.size() - 1;
int end = fromStart ? icons.size() : -1;
int step = fromStart ? 1 : -1;
for (int i = start; i != end; i += step) {
if (isShrinkableIcon(icons.get(i))) {
return i;
}
}
return -1;
}
private boolean isShrinkableIcon(SnapshotPlacement placement) { private boolean isShrinkableIcon(SnapshotPlacement placement) {
return placement != null return placement != null
&& !placement.overflowDot && !placement.overflowDot
@@ -612,15 +443,6 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return result; return result;
} }
private boolean hasOverflowDot(ArrayList<SnapshotPlacement> icons) {
for (SnapshotPlacement icon : icons) {
if (icon.overflowDot) {
return true;
}
}
return false;
}
private ArrayList<SnapshotPlacement> activePlacements() { private ArrayList<SnapshotPlacement> activePlacements() {
if (placements != null) { if (placements != null) {
return placements; return placements;
@@ -884,10 +706,4 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
return kind == LayoutItemKind.CLOCK || kind == LayoutItemKind.CARRIER; return kind == LayoutItemKind.CLOCK || kind == LayoutItemKind.CARRIER;
} }
private static AnchorSide sideFor(String value) {
return "right".equals(value) ? AnchorSide.RIGHT : AnchorSide.LEFT;
}
private record LayoutBandState(boolean placementsWereNull, ArrayList<SnapshotPlacement> placements) {
}
} }
@@ -12,16 +12,15 @@ import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import se.ajpanton.statusbartweak.R; import se.ajpanton.statusbartweak.R;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.AnchorSide; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.AnchorSide;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutEdges;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutItemKind; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutItemKind;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutPosition; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.LayoutPosition;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.SplitRegion; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.SplitRegion;
import se.ajpanton.statusbartweak.runtime.layoutsolver.PackedStatusBarLayoutSolver; import se.ajpanton.statusbartweak.runtime.layoutsolver.PackedStatusBarLayoutSolver;
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle; import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
import se.ajpanton.statusbartweak.runtime.mode.SceneKey; import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings; import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class UnlockedLayoutPlanner { final class UnlockedLayoutPlanner {
@@ -83,7 +82,7 @@ final class UnlockedLayoutPlanner {
? aodStatusContentBounds(root, aodStatusAnchorBounds) ? aodStatusContentBounds(root, aodStatusAnchorBounds)
: null; : null;
Bounds aodNotificationBounds = scene != null && scene.isAod() Bounds aodNotificationBounds = scene != null && scene.isAod()
? aodNotificationBounds(root, anchors, scene) ? aodNotificationBounds(root, scene)
: null; : null;
Bounds aodStatusbarBounds = scene != null && scene.isAod() Bounds aodStatusbarBounds = scene != null && scene.isAod()
? aodStatusbarBounds(root, settings, aodNotificationBounds, aodStatusAnchorBounds) ? aodStatusbarBounds(root, settings, aodNotificationBounds, aodStatusAnchorBounds)
@@ -94,7 +93,7 @@ final class UnlockedLayoutPlanner {
clockHost, clockHost,
clockLayout, clockLayout,
positionFor(settings.clockPosition), positionFor(settings.clockPosition),
settings)); sideFor(settings.clockMiddleCutoutSide)));
} }
ClockLayout carrierLayout = carrierLayout(root, collectedIcons, settings, scene); ClockLayout carrierLayout = carrierLayout(root, collectedIcons, settings, scene);
if (carrierLayout != null && carrierLayout.width() > 0) { if (carrierLayout != null && carrierLayout.width() > 0) {
@@ -102,7 +101,6 @@ final class UnlockedLayoutPlanner {
carrierHost, carrierHost,
carrierLayout, carrierLayout,
positionFor(settings.layoutCarrierPosition), positionFor(settings.layoutCarrierPosition),
settings.layoutCarrierMiddleAutoNearestSide,
sideFor(settings.layoutCarrierMiddleSide))); sideFor(settings.layoutCarrierMiddleSide)));
} }
int statusCount = statusCountForScene(settings, scene); int statusCount = statusCountForScene(settings, scene);
@@ -123,7 +121,6 @@ final class UnlockedLayoutPlanner {
iconHeightPx(statusbarHeight, statusIconHeightSteps(settings, scene))); iconHeightPx(statusbarHeight, statusIconHeightSteps(settings, scene)));
String[] positions = statusPositionsForScene(settings, scene); String[] positions = statusPositionsForScene(settings, scene);
String[] middleSides = statusMiddleSidesForScene(settings, scene); String[] middleSides = statusMiddleSidesForScene(settings, scene);
boolean[] autoNearest = statusAutoNearestForScene(settings, scene);
int[] verticalOffsets = statusVerticalOffsetsForScene(settings, scene); int[] verticalOffsets = statusVerticalOffsetsForScene(settings, scene);
int statusHeightSteps = statusIconHeightSteps(settings, scene); int statusHeightSteps = statusIconHeightSteps(settings, scene);
for (int i = 0; i < statusCount; i++) { for (int i = 0; i < statusCount; i++) {
@@ -148,12 +145,7 @@ final class UnlockedLayoutPlanner {
statusRenderer, statusRenderer,
placements, placements,
positionFor(stringAt(positions, i, settings.layoutStatusPosition)), positionFor(stringAt(positions, i, settings.layoutStatusPosition)),
booleanAt( sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide)))
autoNearest,
i,
settings.layoutStatusMiddleAutoNearestSide),
sideFor(stringAt(middleSides, i, settings.layoutStatusMiddleSide)),
true)
.withSolverCollision( .withSolverCollision(
logicalRowTop(statusHeightSteps, verticalOffsetSteps), logicalRowTop(statusHeightSteps, verticalOffsetSteps),
statusHeightSteps)); statusHeightSteps));
@@ -168,15 +160,19 @@ final class UnlockedLayoutPlanner {
notificationSeenAppReporter.report( notificationSeenAppReporter.report(
root != null ? root.getContext() : null, root != null ? root.getContext() : null,
unfilteredPlacements); unfilteredPlacements);
ArrayList<SnapshotPlacement> filteredPlacements =
SnapshotIconFilter.notificationPlacements(unfilteredPlacements, settings, scene);
if (isDotNotificationScene(scene)) {
filteredPlacements = unreadNotificationPlacements(filteredPlacements);
}
ArrayList<SnapshotPlacement> rawPlacements = resizePlacementsToHeight( ArrayList<SnapshotPlacement> rawPlacements = resizePlacementsToHeight(
SnapshotIconFilter.notificationPlacements(unfilteredPlacements, settings, scene), filteredPlacements,
iconHeightPx(statusbarHeight, notificationIconHeightSteps(settings, scene))); iconHeightPx(statusbarHeight, notificationIconHeightSteps(settings, scene)));
notificationRowBounds = placementBounds(rawPlacements); notificationRowBounds = placementBounds(rawPlacements);
boolean dotNotificationScene = isDotNotificationScene(scene); boolean dotNotificationScene = isDotNotificationScene(scene);
notificationCount = dotNotificationScene && !rawPlacements.isEmpty() ? 1 : notificationCount; notificationCount = dotNotificationScene && !rawPlacements.isEmpty() ? 1 : notificationCount;
String[] positions = notificationPositionsForScene(settings, scene); String[] positions = notificationPositionsForScene(settings, scene);
String[] middleSides = notificationMiddleSidesForScene(settings, scene); String[] middleSides = notificationMiddleSidesForScene(settings, scene);
boolean[] autoNearest = notificationAutoNearestForScene(settings, scene);
int[] verticalOffsets = notificationVerticalOffsetsForScene(settings, scene); int[] verticalOffsets = notificationVerticalOffsetsForScene(settings, scene);
int notificationHeightSteps = notificationIconHeightSteps(settings, scene); int notificationHeightSteps = notificationIconHeightSteps(settings, scene);
for (int i = 0; i < notificationCount; i++) { for (int i = 0; i < notificationCount; i++) {
@@ -195,10 +191,6 @@ final class UnlockedLayoutPlanner {
stepsToPx(verticalOffsetSteps, statusbarHeight)); stepsToPx(verticalOffsetSteps, statusbarHeight));
if (!placements.isEmpty()) { if (!placements.isEmpty()) {
LayoutPosition position = positionFor(stringAt(positions, i, settings.layoutNotifPosition)); LayoutPosition position = positionFor(stringAt(positions, i, settings.layoutNotifPosition));
boolean middleAutoNearest = booleanAt(
autoNearest,
i,
settings.layoutNotifMiddleAutoNearestSide);
AnchorSide middleSide = sideFor(stringAt(middleSides, i, settings.layoutNotifMiddleSide)); AnchorSide middleSide = sideFor(stringAt(middleSides, i, settings.layoutNotifMiddleSide));
bands.add(dotNotificationScene bands.add(dotNotificationScene
? UnlockedLayoutBand.dotIcons( ? UnlockedLayoutBand.dotIcons(
@@ -207,7 +199,6 @@ final class UnlockedLayoutPlanner {
notificationRenderer, notificationRenderer,
placements, placements,
position, position,
middleAutoNearest,
middleSide) middleSide)
.withSolverCollision( .withSolverCollision(
logicalRowTop(notificationHeightSteps, verticalOffsetSteps), logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
@@ -218,9 +209,7 @@ final class UnlockedLayoutPlanner {
notificationRenderer, notificationRenderer,
placements, placements,
position, position,
middleAutoNearest, middleSide)
middleSide,
true)
.withSolverCollision( .withSolverCollision(
logicalRowTop(notificationHeightSteps, verticalOffsetSteps), logicalRowTop(notificationHeightSteps, verticalOffsetSteps),
notificationHeightSteps)); notificationHeightSteps));
@@ -254,9 +243,7 @@ final class UnlockedLayoutPlanner {
chipRenderer, chipRenderer,
placements, placements,
positionFor(settings.layoutChipPosition), positionFor(settings.layoutChipPosition),
settings.layoutChipMiddleAutoNearestSide, sideFor(settings.layoutChipMiddleSide))
sideFor(settings.layoutChipMiddleSide),
false)
.withSolverCollision( .withSolverCollision(
logicalRowTop( logicalRowTop(
settings.layoutChipHeightSteps, settings.layoutChipHeightSteps,
@@ -265,7 +252,7 @@ final class UnlockedLayoutPlanner {
} }
} }
if (bands.isEmpty()) { if (bands.isEmpty()) {
return new LayoutPlan(null, new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); return new LayoutPlan(null, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), null);
} }
ArrayList<LayoutItemKind> itemOrder = orderedKinds(settings.layoutItemOrder); ArrayList<LayoutItemKind> itemOrder = orderedKinds(settings.layoutItemOrder);
splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings); splitClockIfNeeded(root, bands, itemOrder, clockCutoutBounds, settings);
@@ -540,10 +527,6 @@ final class UnlockedLayoutPlanner {
: fallback; : fallback;
} }
private boolean booleanAt(boolean[] values, int index, boolean fallback) {
return values != null && index >= 0 && index < values.length ? values[index] : fallback;
}
private int intAt(int[] values, int index, int fallback) { private int intAt(int[] values, int index, int fallback) {
return values != null && index >= 0 && index < values.length ? values[index] : fallback; return values != null && index >= 0 && index < values.length ? values[index] : fallback;
} }
@@ -726,6 +709,21 @@ final class UnlockedLayoutPlanner {
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT; && scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT;
} }
private ArrayList<SnapshotPlacement> unreadNotificationPlacements(
ArrayList<SnapshotPlacement> placements
) {
if (placements == null || placements.isEmpty()) {
return placements != null ? placements : new ArrayList<>();
}
ArrayList<SnapshotPlacement> unread = new ArrayList<>(placements.size());
for (SnapshotPlacement placement : placements) {
if (placement != null && NotificationUnreadTracker.isUnread(placement.key)) {
unread.add(placement);
}
}
return unread;
}
private String[] statusPositionsForScene(SbtSettings settings, SceneKey scene) { private String[] statusPositionsForScene(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) { if (scene != null && scene.isLockscreen()) {
return settings.layoutStatusLockPositions; return settings.layoutStatusLockPositions;
@@ -746,16 +744,6 @@ final class UnlockedLayoutPlanner {
return settings.layoutStatusMiddleSides; return settings.layoutStatusMiddleSides;
} }
private boolean[] statusAutoNearestForScene(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) {
return settings.layoutStatusLockMiddleAutoNearestSides;
}
if (scene != null && scene.isAod()) {
return settings.layoutStatusAodMiddleAutoNearestSides;
}
return settings.layoutStatusMiddleAutoNearestSides;
}
private int[] statusVerticalOffsetsForScene(SbtSettings settings, SceneKey scene) { private int[] statusVerticalOffsetsForScene(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) { if (scene != null && scene.isLockscreen()) {
return settings.layoutStatusLockVerticalOffsetsPx; return settings.layoutStatusLockVerticalOffsetsPx;
@@ -786,16 +774,6 @@ final class UnlockedLayoutPlanner {
return settings.layoutNotifMiddleSides; return settings.layoutNotifMiddleSides;
} }
private boolean[] notificationAutoNearestForScene(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) {
return settings.layoutNotifLockMiddleAutoNearestSides;
}
if (scene != null && scene.isAod()) {
return settings.layoutNotifAodMiddleAutoNearestSides;
}
return settings.layoutNotifMiddleAutoNearestSides;
}
private int[] notificationVerticalOffsetsForScene(SbtSettings settings, SceneKey scene) { private int[] notificationVerticalOffsetsForScene(SbtSettings settings, SceneKey scene) {
if (scene != null && scene.isLockscreen()) { if (scene != null && scene.isLockscreen()) {
return settings.layoutNotifLockVerticalOffsetsPx; return settings.layoutNotifLockVerticalOffsetsPx;
@@ -1119,21 +1097,11 @@ final class UnlockedLayoutPlanner {
private ArrayList<SnapshotPlacement> bottomAlignAodPlacements( private ArrayList<SnapshotPlacement> bottomAlignAodPlacements(
ArrayList<SnapshotPlacement> placements, ArrayList<SnapshotPlacement> placements,
Bounds aodStatusbarBounds Bounds aodStatusbarBounds
) {
return bottomAlignAodPlacements(placements, aodStatusbarBounds, 0);
}
private ArrayList<SnapshotPlacement> bottomAlignAodPlacements(
ArrayList<SnapshotPlacement> placements,
Bounds aodStatusbarBounds,
int bottomInsetPx
) { ) {
if (placements == null || placements.isEmpty() || aodStatusbarBounds == null) { if (placements == null || placements.isEmpty() || aodStatusbarBounds == null) {
return placements; return placements;
} }
int bottom = aodStatusbarBounds.top int bottom = aodStatusbarBounds.top + aodStatusbarBounds.height;
+ aodStatusbarBounds.height
- Math.max(0, bottomInsetPx);
ArrayList<SnapshotPlacement> result = new ArrayList<>(); ArrayList<SnapshotPlacement> result = new ArrayList<>();
for (SnapshotPlacement placement : placements) { for (SnapshotPlacement placement : placements) {
Bounds bounds = placement.bounds; Bounds bounds = placement.bounds;
@@ -1198,7 +1166,7 @@ final class UnlockedLayoutPlanner {
if (root == null || cutoutBounds == null || bands == null || settings == null) { if (root == null || cutoutBounds == null || bands == null || settings == null) {
return; return;
} }
ArrayList<UnlockedLayoutBand> middleBands = StatusBarLayoutSolver.bandsForPosition( ArrayList<UnlockedLayoutBand> middleBands = bandsForPosition(
bands, bands,
LayoutPosition.MIDDLE, LayoutPosition.MIDDLE,
itemOrder); itemOrder);
@@ -1215,7 +1183,7 @@ final class UnlockedLayoutPlanner {
root.getWidth(), root.getWidth(),
cutoutBounds, cutoutBounds,
settings.clockMiddleAutoNearestSide, settings.clockMiddleAutoNearestSide,
sideFor(settings.clockMiddleCutoutSide)); clockBand.middleSide);
if (splitLayouts.size() < 2) { if (splitLayouts.size() < 2) {
return; return;
} }
@@ -1224,8 +1192,34 @@ final class UnlockedLayoutPlanner {
return; return;
} }
bands.remove(index); bands.remove(index);
bands.add(index, UnlockedLayoutBand.fixedClock(clockBand.host, splitLayouts.get(1), SplitRegion.RIGHT, settings)); bands.add(index, UnlockedLayoutBand.fixedClock(
bands.add(index, UnlockedLayoutBand.fixedClock(clockBand.host, splitLayouts.get(0), SplitRegion.LEFT, settings)); clockBand.host,
splitLayouts.get(1),
SplitRegion.RIGHT,
clockBand.middleSide));
bands.add(index, UnlockedLayoutBand.fixedClock(
clockBand.host,
splitLayouts.get(0),
SplitRegion.LEFT,
clockBand.middleSide));
}
private ArrayList<UnlockedLayoutBand> bandsForPosition(
ArrayList<UnlockedLayoutBand> bands,
LayoutPosition position,
ArrayList<LayoutItemKind> itemOrder
) {
ArrayList<UnlockedLayoutBand> result = new ArrayList<>();
for (LayoutItemKind kind : itemOrder) {
for (UnlockedLayoutBand band : bands) {
if (band.kind == kind
&& band.position == position
&& band.splitRegion == SplitRegion.NONE) {
result.add(band);
}
}
}
return result;
} }
private LayoutEdges layoutEdges( private LayoutEdges layoutEdges(
@@ -1240,7 +1234,6 @@ final class UnlockedLayoutPlanner {
LayoutEdges aodEdges = aodBurnInEdges( LayoutEdges aodEdges = aodBurnInEdges(
root, root,
settings, settings,
anchors,
scene, scene,
rootWidth, rootWidth,
aodStatusAnchorBounds); aodStatusAnchorBounds);
@@ -1295,7 +1288,6 @@ final class UnlockedLayoutPlanner {
private LayoutEdges aodBurnInEdges( private LayoutEdges aodBurnInEdges(
View root, View root,
SbtSettings settings, SbtSettings settings,
RootAnchors anchors,
SceneKey scene, SceneKey scene,
int rootWidth, int rootWidth,
Bounds statusBounds Bounds statusBounds
@@ -1303,7 +1295,7 @@ final class UnlockedLayoutPlanner {
if (root == null || settings == null || rootWidth <= 0) { if (root == null || settings == null || rootWidth <= 0) {
return null; return null;
} }
Bounds notificationBounds = aodNotificationBounds(root, anchors, scene); Bounds notificationBounds = aodNotificationBounds(root, scene);
Bounds bounds = aodStatusbarBounds(root, settings, notificationBounds, statusBounds); Bounds bounds = aodStatusbarBounds(root, settings, notificationBounds, statusBounds);
if (bounds == null) { if (bounds == null) {
return null; return null;
@@ -1350,7 +1342,7 @@ final class UnlockedLayoutPlanner {
if (root == null || root.getWidth() <= 0) { if (root == null || root.getWidth() <= 0) {
return null; return null;
} }
Bounds notificationBounds = aodNotificationBounds(root, anchors, scene); Bounds notificationBounds = aodNotificationBounds(root, scene);
Bounds liveMovingStatusBounds = AodLiveStatusbarSource.movingBoundsForRoot(root); Bounds liveMovingStatusBounds = AodLiveStatusbarSource.movingBoundsForRoot(root);
Bounds storedStatusBounds = AodStatusbarSourceStore.statusBoundsForRoot( Bounds storedStatusBounds = AodStatusbarSourceStore.statusBoundsForRoot(
root, root,
@@ -1404,7 +1396,7 @@ final class UnlockedLayoutPlanner {
liveMovingStatusBounds.height); liveMovingStatusBounds.height);
} }
private Bounds aodNotificationBounds(View root, RootAnchors anchors, SceneKey scene) { private Bounds aodNotificationBounds(View root, SceneKey scene) {
if (scene != null if (scene != null
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) { && scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) {
return null; return null;
@@ -1626,6 +1618,9 @@ final class UnlockedLayoutPlanner {
return null; return null;
} }
private record LayoutEdges(int left, int right) {
}
private record StockInsets(int left, int right) { private record StockInsets(int left, int right) {
} }
} }
@@ -15,11 +15,14 @@ import java.util.Locale;
import java.util.Objects; import java.util.Objects;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import se.ajpanton.statusbartweak.runtime.NotificationKeyReflection;
import se.ajpanton.statusbartweak.runtime.ViewIdNames; import se.ajpanton.statusbartweak.runtime.ViewIdNames;
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport; import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds; import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle; import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
import se.ajpanton.statusbartweak.runtime.mode.SceneKey; import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationActiveKeyStore;
import se.ajpanton.statusbartweak.runtime.notifications.NotificationUnreadTracker;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings; import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class UnlockedStockSourceCollector { final class UnlockedStockSourceCollector {
@@ -76,6 +79,12 @@ final class UnlockedStockSourceCollector {
|| scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT) { || scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT) {
notificationIcons.addAll( notificationIcons.addAll(
LockscreenCardsNotificationIconSourceStore.snapshotSourcesForAodIconsRoot(root)); LockscreenCardsNotificationIconSourceStore.snapshotSourcesForAodIconsRoot(root));
if (notificationIcons.isEmpty()
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT) {
notificationIcons.addAll(
LockscreenCardsNotificationIconSourceStore
.snapshotAodNotificationPackageSources(root));
}
} }
} else if (anchors.notificationRoot != null) { } else if (anchors.notificationRoot != null) {
collectNotificationSnapshotViews(anchors.notificationRoot, notificationIcons); collectNotificationSnapshotViews(anchors.notificationRoot, notificationIcons);
@@ -178,6 +187,16 @@ final class UnlockedStockSourceCollector {
statusSourceSignature = 31 * statusSourceSignature statusSourceSignature = 31 * statusSourceSignature
+ aodLayoutAnchorSignature(root, anchors, scene); + aodLayoutAnchorSignature(root, anchors, scene);
} }
int notificationSourceSignature = sourceLayoutListSignature(
previousIcons != null ? previousIcons.notificationIcons : null);
notificationSourceSignature = 31 * notificationSourceSignature
+ NotificationActiveKeyStore.generation();
if (scene != null
&& (scene.isAod() || scene.isLockscreen())
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT) {
notificationSourceSignature = 31 * notificationSourceSignature
+ NotificationUnreadTracker.generation();
}
return new LayoutInputSignature( return new LayoutInputSignature(
scene != null ? scene.toString() : "", scene != null ? scene.toString() : "",
root.getWidth(), root.getWidth(),
@@ -188,7 +207,7 @@ final class UnlockedStockSourceCollector {
cutout != null ? cutout.top : Integer.MIN_VALUE, cutout != null ? cutout.top : Integer.MIN_VALUE,
cutout != null ? cutout.right : Integer.MIN_VALUE, cutout != null ? cutout.right : Integer.MIN_VALUE,
cutout != null ? cutout.bottom : Integer.MIN_VALUE, cutout != null ? cutout.bottom : Integer.MIN_VALUE,
loggingAwareSettingsSignature(root, settings), layoutSettingsSignature(settings),
clockTimeSignature(settings), clockTimeSignature(settings),
viewSignatureOrZero(anchors != null ? anchors.clockView : null), viewSignatureOrZero(anchors != null ? anchors.clockView : null),
shallowTreeSignatureExcluding(anchors != null ? anchors.clockContainer : null, null), shallowTreeSignatureExcluding(anchors != null ? anchors.clockContainer : null, null),
@@ -207,7 +226,7 @@ final class UnlockedStockSourceCollector {
notificationRootSignature(anchors != null ? anchors.notificationRoot : null), notificationRootSignature(anchors != null ? anchors.notificationRoot : null),
viewSignatureOrZero(anchors != null ? anchors.carrierView : null), viewSignatureOrZero(anchors != null ? anchors.carrierView : null),
statusSourceSignature, statusSourceSignature,
sourceLayoutListSignature(previousIcons != null ? previousIcons.notificationIcons : null), notificationSourceSignature,
chipSourceSignature); chipSourceSignature);
} }
@@ -682,7 +701,13 @@ final class UnlockedStockSourceCollector {
private void collectNotificationSnapshotViews(View source, ArrayList<SnapshotSource> out) { private void collectNotificationSnapshotViews(View source, ArrayList<SnapshotSource> out) {
if (isNotificationSnapshotCandidate(source)) { if (isNotificationSnapshotCandidate(source)) {
out.add(new SnapshotSource(source, SnapshotMode.NOTIFICATION_DRAWABLE)); String key = NotificationKeyReflection.keyForIconView(source);
if (key != null
&& NotificationActiveKeyStore.hasSnapshot()
&& !NotificationActiveKeyStore.isActive(key)) {
return;
}
out.add(new SnapshotSource(source, SnapshotMode.NOTIFICATION_DRAWABLE, key));
return; return;
} }
if (source instanceof ViewGroup group) { if (source instanceof ViewGroup group) {
@@ -967,22 +992,7 @@ final class UnlockedStockSourceCollector {
if (view == null) { if (view == null) {
return 0; return 0;
} }
int result = 17; return sourceLayoutSignature(view);
result = 31 * result + System.identityHashCode(view);
result = 31 * result + view.getClass().getName().hashCode();
result = 31 * result + view.getId();
result = 31 * result + view.getVisibility();
if (view instanceof ViewGroup group) {
result = 31 * result + group.getChildCount();
for (int i = 0; i < group.getChildCount(); i++) {
View child = group.getChildAt(i);
result = 31 * result + System.identityHashCode(child);
result = 31 * result + child.getClass().getName().hashCode();
result = 31 * result + child.getId();
result = 31 * result + child.getVisibility();
}
}
return result;
} }
private static int sourceLayoutListSignature(ArrayList<SnapshotSource> sources) { private static int sourceLayoutListSignature(ArrayList<SnapshotSource> sources) {
@@ -1007,6 +1017,7 @@ final class UnlockedStockSourceCollector {
int result = 17; int result = 17;
result = 31 * result + System.identityHashCode(view); result = 31 * result + System.identityHashCode(view);
result = 31 * result + view.getClass().getName().hashCode(); result = 31 * result + view.getClass().getName().hashCode();
result = 31 * result + (view.isAttachedToWindow() ? 1 : 0);
result = 31 * result + view.getId(); result = 31 * result + view.getId();
result = 31 * result + view.getVisibility(); result = 31 * result + view.getVisibility();
result = 31 * result + width; result = 31 * result + width;
@@ -1207,12 +1218,10 @@ final class UnlockedStockSourceCollector {
settings.layoutCarrierPosition, settings.layoutCarrierPosition,
settings.layoutCarrierEnabledLockscreen, settings.layoutCarrierEnabledLockscreen,
settings.layoutCarrierMiddleSide, settings.layoutCarrierMiddleSide,
settings.layoutCarrierMiddleAutoNearestSide,
settings.layoutCarrierVerticalOffsetPx, settings.layoutCarrierVerticalOffsetPx,
settings.layoutChipPosition, settings.layoutChipPosition,
settings.layoutChipEnabledUnlocked, settings.layoutChipEnabledUnlocked,
settings.layoutChipMiddleSide, settings.layoutChipMiddleSide,
settings.layoutChipMiddleAutoNearestSide,
settings.layoutChipVerticalOffsetPx, settings.layoutChipVerticalOffsetPx,
settings.layoutChipHeightSteps, settings.layoutChipHeightSteps,
settings.layoutNotifPosition, settings.layoutNotifPosition,
@@ -1221,44 +1230,36 @@ final class UnlockedStockSourceCollector {
settings.layoutNotifUnlockedCount, settings.layoutNotifUnlockedCount,
Arrays.hashCode(settings.layoutNotifPositions), Arrays.hashCode(settings.layoutNotifPositions),
Arrays.hashCode(settings.layoutNotifMiddleSides), Arrays.hashCode(settings.layoutNotifMiddleSides),
Arrays.hashCode(settings.layoutNotifMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutNotifVerticalOffsetsPx), Arrays.hashCode(settings.layoutNotifVerticalOffsetsPx),
settings.layoutNotifEnabledLockscreen, settings.layoutNotifEnabledLockscreen,
settings.layoutNotifLockCount, settings.layoutNotifLockCount,
Arrays.hashCode(settings.layoutNotifLockPositions), Arrays.hashCode(settings.layoutNotifLockPositions),
Arrays.hashCode(settings.layoutNotifLockMiddleSides), Arrays.hashCode(settings.layoutNotifLockMiddleSides),
Arrays.hashCode(settings.layoutNotifLockMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutNotifLockVerticalOffsetsPx), Arrays.hashCode(settings.layoutNotifLockVerticalOffsetsPx),
settings.layoutNotifEnabledAod, settings.layoutNotifEnabledAod,
settings.layoutNotifAodCount, settings.layoutNotifAodCount,
Arrays.hashCode(settings.layoutNotifAodPositions), Arrays.hashCode(settings.layoutNotifAodPositions),
Arrays.hashCode(settings.layoutNotifAodMiddleSides), Arrays.hashCode(settings.layoutNotifAodMiddleSides),
Arrays.hashCode(settings.layoutNotifAodMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutNotifAodVerticalOffsetsPx), Arrays.hashCode(settings.layoutNotifAodVerticalOffsetsPx),
settings.layoutNotifMiddleSide, settings.layoutNotifMiddleSide,
settings.layoutNotifMiddleAutoNearestSide,
settings.layoutNotifVerticalOffsetPx, settings.layoutNotifVerticalOffsetPx,
settings.layoutStatusPosition, settings.layoutStatusPosition,
settings.layoutStatusEnabledUnlocked, settings.layoutStatusEnabledUnlocked,
settings.layoutStatusUnlockedCount, settings.layoutStatusUnlockedCount,
Arrays.hashCode(settings.layoutStatusPositions), Arrays.hashCode(settings.layoutStatusPositions),
Arrays.hashCode(settings.layoutStatusMiddleSides), Arrays.hashCode(settings.layoutStatusMiddleSides),
Arrays.hashCode(settings.layoutStatusMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutStatusVerticalOffsetsPx), Arrays.hashCode(settings.layoutStatusVerticalOffsetsPx),
settings.layoutStatusEnabledLockscreen, settings.layoutStatusEnabledLockscreen,
settings.layoutStatusLockCount, settings.layoutStatusLockCount,
Arrays.hashCode(settings.layoutStatusLockPositions), Arrays.hashCode(settings.layoutStatusLockPositions),
Arrays.hashCode(settings.layoutStatusLockMiddleSides), Arrays.hashCode(settings.layoutStatusLockMiddleSides),
Arrays.hashCode(settings.layoutStatusLockMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutStatusLockVerticalOffsetsPx), Arrays.hashCode(settings.layoutStatusLockVerticalOffsetsPx),
settings.layoutStatusEnabledAod, settings.layoutStatusEnabledAod,
settings.layoutStatusAodCount, settings.layoutStatusAodCount,
Arrays.hashCode(settings.layoutStatusAodPositions), Arrays.hashCode(settings.layoutStatusAodPositions),
Arrays.hashCode(settings.layoutStatusAodMiddleSides), Arrays.hashCode(settings.layoutStatusAodMiddleSides),
Arrays.hashCode(settings.layoutStatusAodMiddleAutoNearestSides),
Arrays.hashCode(settings.layoutStatusAodVerticalOffsetsPx), Arrays.hashCode(settings.layoutStatusAodVerticalOffsetsPx),
settings.layoutStatusMiddleSide, settings.layoutStatusMiddleSide,
settings.layoutStatusMiddleAutoNearestSide,
settings.layoutStatusVerticalOffsetPx, settings.layoutStatusVerticalOffsetPx,
settings.systemIconBlockedModes, settings.systemIconBlockedModes,
settings.appIconBlockedModes, settings.appIconBlockedModes,
@@ -1269,11 +1270,4 @@ final class UnlockedStockSourceCollector {
settings.statusChipsHideCallUnlocked); settings.statusChipsHideCallUnlocked);
} }
private int loggingAwareSettingsSignature(View root, SbtSettings settings) {
int result = layoutSettingsSignature(settings);
boolean logsEnabled = root != null
&& root.getContext() != null
&& SbtSettings.isDebugLogWritingEnabled(root.getContext());
return 31 * result + (logsEnabled ? 1 : 0);
}
} }
@@ -107,24 +107,19 @@ public final class SbtDefaults {
public static final String LAYOUT_CARRIER_POSITION_DEFAULT = "left"; public static final String LAYOUT_CARRIER_POSITION_DEFAULT = "left";
public static final boolean LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT = true; public static final boolean LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT = true;
public static final String LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT = "left"; public static final String LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT = "left";
public static final boolean LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT = true;
public static final int LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT = 0; public static final int LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT = 0;
public static final String LAYOUT_CHIP_POSITION_DEFAULT = "left"; public static final String LAYOUT_CHIP_POSITION_DEFAULT = "left";
public static final boolean LAYOUT_CHIP_ENABLED_LOCKSCREEN_DEFAULT = true;
public static final boolean LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT = true; public static final boolean LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT = true;
public static final String LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT = "left"; public static final String LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT = "left";
public static final boolean LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT = true;
public static final int LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT = 0; public static final int LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT = 0;
public static final int LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT = 52; public static final int LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT = 52;
public static final String LAYOUT_NOTIF_POSITION_DEFAULT = "left"; public static final String LAYOUT_NOTIF_POSITION_DEFAULT = "left";
public static final String LAYOUT_NOTIF_SORT_ORDER_DEFAULT = "automatic"; public static final String LAYOUT_NOTIF_SORT_ORDER_DEFAULT = "automatic";
public static final boolean LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT = true;
public static final boolean LAYOUT_NOTIF_ENABLED_AOD_DEFAULT = true; public static final boolean LAYOUT_NOTIF_ENABLED_AOD_DEFAULT = true;
public static final boolean LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT = true; public static final boolean LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT = true;
public static final boolean LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT = true; public static final boolean LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT = true;
public static final int LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT = 1; public static final int LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT = 1;
public static final String LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT = "left"; public static final String LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT = "left";
public static final boolean LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT = true;
public static final int LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT = 0; public static final int LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT = 0;
public static final int LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT = 46; public static final int LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT = 46;
public static final int LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT = 46; public static final int LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT = 46;
@@ -136,9 +131,7 @@ public final class SbtDefaults {
public static final boolean LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT = true; public static final boolean LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT = true;
public static final boolean LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT = true; public static final boolean LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT = true;
public static final int LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT = 1; public static final int LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT = 1;
public static final boolean LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED_DEFAULT = true;
public static final String LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT = "left"; public static final String LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT = "left";
public static final boolean LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT = true;
public static final int LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT = 0; public static final int LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT = 0;
public static final int LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT = 38; public static final int LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT = 38;
public static final int LAYOUT_ICON_HEIGHT_STEPS_MIN = 10; public static final int LAYOUT_ICON_HEIGHT_STEPS_MIN = 10;
@@ -103,18 +103,14 @@ public final class SbtSettings {
public static final String KEY_LAYOUT_CARRIER_POSITION = "layout_carrier_position"; public static final String KEY_LAYOUT_CARRIER_POSITION = "layout_carrier_position";
public static final String KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN = "layout_carrier_enabled_lockscreen"; public static final String KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN = "layout_carrier_enabled_lockscreen";
public static final String KEY_LAYOUT_CARRIER_MIDDLE_SIDE = "layout_carrier_middle_side"; public static final String KEY_LAYOUT_CARRIER_MIDDLE_SIDE = "layout_carrier_middle_side";
public static final String KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE = "layout_carrier_middle_auto_nearest_side";
public static final String KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX = "layout_carrier_vertical_offset_px"; public static final String KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX = "layout_carrier_vertical_offset_px";
public static final String KEY_LAYOUT_CHIP_POSITION = "layout_chip_position"; public static final String KEY_LAYOUT_CHIP_POSITION = "layout_chip_position";
public static final String KEY_LAYOUT_CHIP_ENABLED_LOCKSCREEN = "layout_chip_enabled_lockscreen";
public static final String KEY_LAYOUT_CHIP_ENABLED_UNLOCKED = "layout_chip_enabled_unlocked"; public static final String KEY_LAYOUT_CHIP_ENABLED_UNLOCKED = "layout_chip_enabled_unlocked";
public static final String KEY_LAYOUT_CHIP_MIDDLE_SIDE = "layout_chip_middle_side"; public static final String KEY_LAYOUT_CHIP_MIDDLE_SIDE = "layout_chip_middle_side";
public static final String KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE = "layout_chip_middle_auto_nearest_side";
public static final String KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX = "layout_chip_vertical_offset_px"; public static final String KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX = "layout_chip_vertical_offset_px";
public static final String KEY_LAYOUT_CHIP_HEIGHT_STEPS = "layout_chip_height_steps"; public static final String KEY_LAYOUT_CHIP_HEIGHT_STEPS = "layout_chip_height_steps";
public static final String KEY_LAYOUT_NOTIF_POSITION = "layout_notif_position"; public static final String KEY_LAYOUT_NOTIF_POSITION = "layout_notif_position";
public static final String KEY_LAYOUT_NOTIF_SORT_ORDER = "layout_notif_sort_order"; public static final String KEY_LAYOUT_NOTIF_SORT_ORDER = "layout_notif_sort_order";
public static final String KEY_LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED = "layout_notif_show_dot_if_truncated";
public static final String KEY_LAYOUT_NOTIF_ENABLED_AOD = "layout_notif_enabled_aod"; public static final String KEY_LAYOUT_NOTIF_ENABLED_AOD = "layout_notif_enabled_aod";
public static final String KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN = "layout_notif_enabled_lockscreen"; public static final String KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN = "layout_notif_enabled_lockscreen";
public static final String KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED = "layout_notif_enabled_unlocked"; public static final String KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED = "layout_notif_enabled_unlocked";
@@ -123,22 +119,17 @@ public final class SbtSettings {
public static final String KEY_LAYOUT_NOTIF_AOD_COUNT = "layout_aod_notifications_count"; public static final String KEY_LAYOUT_NOTIF_AOD_COUNT = "layout_aod_notifications_count";
public static final String KEY_LAYOUT_NOTIF_LOCK_POSITION = "layout_lock_notifications_position"; public static final String KEY_LAYOUT_NOTIF_LOCK_POSITION = "layout_lock_notifications_position";
public static final String KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE = "layout_lock_notifications_middle_side"; public static final String KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE = "layout_lock_notifications_middle_side";
public static final String KEY_LAYOUT_NOTIF_LOCK_MIDDLE_AUTO_NEAREST_SIDE =
"layout_lock_notifications_middle_auto_nearest_side";
public static final String KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX = public static final String KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX =
"layout_lock_notifications_vertical_offset_px"; "layout_lock_notifications_vertical_offset_px";
public static final String KEY_LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS = public static final String KEY_LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS =
"layout_lock_notifications_icon_height_steps"; "layout_lock_notifications_icon_height_steps";
public static final String KEY_LAYOUT_NOTIF_AOD_POSITION = "layout_aod_notifications_position"; public static final String KEY_LAYOUT_NOTIF_AOD_POSITION = "layout_aod_notifications_position";
public static final String KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE = "layout_aod_notifications_middle_side"; public static final String KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE = "layout_aod_notifications_middle_side";
public static final String KEY_LAYOUT_NOTIF_AOD_MIDDLE_AUTO_NEAREST_SIDE =
"layout_aod_notifications_middle_auto_nearest_side";
public static final String KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX = public static final String KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX =
"layout_aod_notifications_vertical_offset_px"; "layout_aod_notifications_vertical_offset_px";
public static final String KEY_LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS = public static final String KEY_LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS =
"layout_aod_notifications_icon_height_steps"; "layout_aod_notifications_icon_height_steps";
public static final String KEY_LAYOUT_NOTIF_MIDDLE_SIDE = "layout_notif_middle_side"; public static final String KEY_LAYOUT_NOTIF_MIDDLE_SIDE = "layout_notif_middle_side";
public static final String KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE = "layout_notif_middle_auto_nearest_side";
public static final String KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX = "layout_notif_vertical_offset_px"; public static final String KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX = "layout_notif_vertical_offset_px";
public static final String KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS = "layout_notif_icon_height_steps"; public static final String KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS = "layout_notif_icon_height_steps";
public static final String KEY_LAYOUT_STATUS_POSITION = "layout_status_position"; public static final String KEY_LAYOUT_STATUS_POSITION = "layout_status_position";
@@ -150,23 +141,17 @@ public final class SbtSettings {
public static final String KEY_LAYOUT_STATUS_AOD_COUNT = "layout_aod_status_count"; public static final String KEY_LAYOUT_STATUS_AOD_COUNT = "layout_aod_status_count";
public static final String KEY_LAYOUT_STATUS_LOCK_POSITION = "layout_lock_status_position"; public static final String KEY_LAYOUT_STATUS_LOCK_POSITION = "layout_lock_status_position";
public static final String KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE = "layout_lock_status_middle_side"; public static final String KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE = "layout_lock_status_middle_side";
public static final String KEY_LAYOUT_STATUS_LOCK_MIDDLE_AUTO_NEAREST_SIDE =
"layout_lock_status_middle_auto_nearest_side";
public static final String KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX = public static final String KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX =
"layout_lock_status_vertical_offset_px"; "layout_lock_status_vertical_offset_px";
public static final String KEY_LAYOUT_STATUS_LOCK_ICON_HEIGHT_STEPS = public static final String KEY_LAYOUT_STATUS_LOCK_ICON_HEIGHT_STEPS =
"layout_lock_status_icon_height_steps"; "layout_lock_status_icon_height_steps";
public static final String KEY_LAYOUT_STATUS_AOD_POSITION = "layout_aod_status_position"; public static final String KEY_LAYOUT_STATUS_AOD_POSITION = "layout_aod_status_position";
public static final String KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE = "layout_aod_status_middle_side"; public static final String KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE = "layout_aod_status_middle_side";
public static final String KEY_LAYOUT_STATUS_AOD_MIDDLE_AUTO_NEAREST_SIDE =
"layout_aod_status_middle_auto_nearest_side";
public static final String KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX = public static final String KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX =
"layout_aod_status_vertical_offset_px"; "layout_aod_status_vertical_offset_px";
public static final String KEY_LAYOUT_STATUS_AOD_ICON_HEIGHT_STEPS = public static final String KEY_LAYOUT_STATUS_AOD_ICON_HEIGHT_STEPS =
"layout_aod_status_icon_height_steps"; "layout_aod_status_icon_height_steps";
public static final String KEY_LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED = "layout_status_show_dot_if_truncated";
public static final String KEY_LAYOUT_STATUS_MIDDLE_SIDE = "layout_status_middle_side"; public static final String KEY_LAYOUT_STATUS_MIDDLE_SIDE = "layout_status_middle_side";
public static final String KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE = "layout_status_middle_auto_nearest_side";
public static final String KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX = "layout_status_vertical_offset_px"; public static final String KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX = "layout_status_vertical_offset_px";
public static final String KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS = "layout_status_icon_height_steps"; public static final String KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS = "layout_status_icon_height_steps";
public static final String KEY_SYSTEM_ICON_BLOCKED_MODES = SystemIconRules.PREF_KEY_BLOCKED_MODES; public static final String KEY_SYSTEM_ICON_BLOCKED_MODES = SystemIconRules.PREF_KEY_BLOCKED_MODES;
@@ -182,10 +167,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, index);
} }
public static String layoutNotifMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutNotifVerticalOffsetKey(int index) { public static String layoutNotifVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, index);
} }
@@ -198,10 +179,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_STATUS_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_STATUS_MIDDLE_SIDE, index);
} }
public static String layoutStatusMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutStatusVerticalOffsetKey(int index) { public static String layoutStatusVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, index);
} }
@@ -214,10 +191,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE, index);
} }
public static String layoutLockNotifMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_LOCK_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutLockNotifVerticalOffsetKey(int index) { public static String layoutLockNotifVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX, index);
} }
@@ -234,10 +207,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE, index);
} }
public static String layoutAodNotifMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_AOD_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutAodNotifVerticalOffsetKey(int index) { public static String layoutAodNotifVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX, index);
} }
@@ -254,10 +223,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE, index);
} }
public static String layoutLockStatusMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_LOCK_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutLockStatusVerticalOffsetKey(int index) { public static String layoutLockStatusVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX, index);
} }
@@ -274,10 +239,6 @@ public final class SbtSettings {
return suffixedKey(KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE, index); return suffixedKey(KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE, index);
} }
public static String layoutAodStatusMiddleAutoNearestSideKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_AOD_MIDDLE_AUTO_NEAREST_SIDE, index);
}
public static String layoutAodStatusVerticalOffsetKey(int index) { public static String layoutAodStatusVerticalOffsetKey(int index) {
return suffixedKey(KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX, index); return suffixedKey(KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX, index);
} }
@@ -350,38 +311,30 @@ public final class SbtSettings {
public final String layoutCarrierPosition; public final String layoutCarrierPosition;
public final boolean layoutCarrierEnabledLockscreen; public final boolean layoutCarrierEnabledLockscreen;
public final String layoutCarrierMiddleSide; public final String layoutCarrierMiddleSide;
public final boolean layoutCarrierMiddleAutoNearestSide;
public final int layoutCarrierVerticalOffsetPx; public final int layoutCarrierVerticalOffsetPx;
public final String layoutChipPosition; public final String layoutChipPosition;
public final boolean layoutChipEnabledLockscreen;
public final boolean layoutChipEnabledUnlocked; public final boolean layoutChipEnabledUnlocked;
public final String layoutChipMiddleSide; public final String layoutChipMiddleSide;
public final boolean layoutChipMiddleAutoNearestSide;
public final int layoutChipVerticalOffsetPx; public final int layoutChipVerticalOffsetPx;
public final int layoutChipHeightSteps; public final int layoutChipHeightSteps;
public final String layoutNotifPosition; public final String layoutNotifPosition;
public final String layoutNotifSortOrder; public final String layoutNotifSortOrder;
public final boolean layoutNotifShowDotIfTruncated;
public final boolean layoutNotifEnabledAod; public final boolean layoutNotifEnabledAod;
public final boolean layoutNotifEnabledLockscreen; public final boolean layoutNotifEnabledLockscreen;
public final boolean layoutNotifEnabledUnlocked; public final boolean layoutNotifEnabledUnlocked;
public final int layoutNotifUnlockedCount; public final int layoutNotifUnlockedCount;
public final String[] layoutNotifPositions; public final String[] layoutNotifPositions;
public final String[] layoutNotifMiddleSides; public final String[] layoutNotifMiddleSides;
public final boolean[] layoutNotifMiddleAutoNearestSides;
public final int[] layoutNotifVerticalOffsetsPx; public final int[] layoutNotifVerticalOffsetsPx;
public final int layoutNotifLockCount; public final int layoutNotifLockCount;
public final String[] layoutNotifLockPositions; public final String[] layoutNotifLockPositions;
public final String[] layoutNotifLockMiddleSides; public final String[] layoutNotifLockMiddleSides;
public final boolean[] layoutNotifLockMiddleAutoNearestSides;
public final int[] layoutNotifLockVerticalOffsetsPx; public final int[] layoutNotifLockVerticalOffsetsPx;
public final int layoutNotifAodCount; public final int layoutNotifAodCount;
public final String[] layoutNotifAodPositions; public final String[] layoutNotifAodPositions;
public final String[] layoutNotifAodMiddleSides; public final String[] layoutNotifAodMiddleSides;
public final boolean[] layoutNotifAodMiddleAutoNearestSides;
public final int[] layoutNotifAodVerticalOffsetsPx; public final int[] layoutNotifAodVerticalOffsetsPx;
public final String layoutNotifMiddleSide; public final String layoutNotifMiddleSide;
public final boolean layoutNotifMiddleAutoNearestSide;
public final int layoutNotifVerticalOffsetPx; public final int layoutNotifVerticalOffsetPx;
public final int layoutNotifIconHeightSteps; public final int layoutNotifIconHeightSteps;
public final int layoutNotifLockIconHeightSteps; public final int layoutNotifLockIconHeightSteps;
@@ -393,21 +346,16 @@ public final class SbtSettings {
public final int layoutStatusUnlockedCount; public final int layoutStatusUnlockedCount;
public final String[] layoutStatusPositions; public final String[] layoutStatusPositions;
public final String[] layoutStatusMiddleSides; public final String[] layoutStatusMiddleSides;
public final boolean[] layoutStatusMiddleAutoNearestSides;
public final int[] layoutStatusVerticalOffsetsPx; public final int[] layoutStatusVerticalOffsetsPx;
public final int layoutStatusLockCount; public final int layoutStatusLockCount;
public final String[] layoutStatusLockPositions; public final String[] layoutStatusLockPositions;
public final String[] layoutStatusLockMiddleSides; public final String[] layoutStatusLockMiddleSides;
public final boolean[] layoutStatusLockMiddleAutoNearestSides;
public final int[] layoutStatusLockVerticalOffsetsPx; public final int[] layoutStatusLockVerticalOffsetsPx;
public final int layoutStatusAodCount; public final int layoutStatusAodCount;
public final String[] layoutStatusAodPositions; public final String[] layoutStatusAodPositions;
public final String[] layoutStatusAodMiddleSides; public final String[] layoutStatusAodMiddleSides;
public final boolean[] layoutStatusAodMiddleAutoNearestSides;
public final int[] layoutStatusAodVerticalOffsetsPx; public final int[] layoutStatusAodVerticalOffsetsPx;
public final boolean layoutStatusShowDotIfTruncated;
public final String layoutStatusMiddleSide; public final String layoutStatusMiddleSide;
public final boolean layoutStatusMiddleAutoNearestSide;
public final int layoutStatusVerticalOffsetPx; public final int layoutStatusVerticalOffsetPx;
public final int layoutStatusIconHeightSteps; public final int layoutStatusIconHeightSteps;
public final int layoutStatusLockIconHeightSteps; public final int layoutStatusLockIconHeightSteps;
@@ -485,23 +433,18 @@ public final class SbtSettings {
String layoutCarrierPosition, String layoutCarrierPosition,
boolean layoutCarrierEnabledLockscreen, boolean layoutCarrierEnabledLockscreen,
String layoutCarrierMiddleSide, String layoutCarrierMiddleSide,
boolean layoutCarrierMiddleAutoNearestSide,
int layoutCarrierVerticalOffsetPx, int layoutCarrierVerticalOffsetPx,
String layoutChipPosition, String layoutChipPosition,
boolean layoutChipEnabledLockscreen,
boolean layoutChipEnabledUnlocked, boolean layoutChipEnabledUnlocked,
String layoutChipMiddleSide, String layoutChipMiddleSide,
boolean layoutChipMiddleAutoNearestSide,
int layoutChipVerticalOffsetPx, int layoutChipVerticalOffsetPx,
int layoutChipHeightSteps, int layoutChipHeightSteps,
String layoutNotifPosition, String layoutNotifPosition,
String layoutNotifSortOrder, String layoutNotifSortOrder,
boolean layoutNotifShowDotIfTruncated,
boolean layoutNotifEnabledAod, boolean layoutNotifEnabledAod,
boolean layoutNotifEnabledLockscreen, boolean layoutNotifEnabledLockscreen,
boolean layoutNotifEnabledUnlocked, boolean layoutNotifEnabledUnlocked,
String layoutNotifMiddleSide, String layoutNotifMiddleSide,
boolean layoutNotifMiddleAutoNearestSide,
int layoutNotifVerticalOffsetPx, int layoutNotifVerticalOffsetPx,
int layoutNotifIconHeightSteps, int layoutNotifIconHeightSteps,
int layoutNotifLockIconHeightSteps, int layoutNotifLockIconHeightSteps,
@@ -509,25 +452,20 @@ public final class SbtSettings {
int layoutNotifUnlockedCount, int layoutNotifUnlockedCount,
String[] layoutNotifPositions, String[] layoutNotifPositions,
String[] layoutNotifMiddleSides, String[] layoutNotifMiddleSides,
boolean[] layoutNotifMiddleAutoNearestSides,
int[] layoutNotifVerticalOffsetsPx, int[] layoutNotifVerticalOffsetsPx,
int layoutNotifLockCount, int layoutNotifLockCount,
String[] layoutNotifLockPositions, String[] layoutNotifLockPositions,
String[] layoutNotifLockMiddleSides, String[] layoutNotifLockMiddleSides,
boolean[] layoutNotifLockMiddleAutoNearestSides,
int[] layoutNotifLockVerticalOffsetsPx, int[] layoutNotifLockVerticalOffsetsPx,
int layoutNotifAodCount, int layoutNotifAodCount,
String[] layoutNotifAodPositions, String[] layoutNotifAodPositions,
String[] layoutNotifAodMiddleSides, String[] layoutNotifAodMiddleSides,
boolean[] layoutNotifAodMiddleAutoNearestSides,
int[] layoutNotifAodVerticalOffsetsPx, int[] layoutNotifAodVerticalOffsetsPx,
String layoutStatusPosition, String layoutStatusPosition,
boolean layoutStatusEnabledAod, boolean layoutStatusEnabledAod,
boolean layoutStatusEnabledLockscreen, boolean layoutStatusEnabledLockscreen,
boolean layoutStatusEnabledUnlocked, boolean layoutStatusEnabledUnlocked,
boolean layoutStatusShowDotIfTruncated,
String layoutStatusMiddleSide, String layoutStatusMiddleSide,
boolean layoutStatusMiddleAutoNearestSide,
int layoutStatusVerticalOffsetPx, int layoutStatusVerticalOffsetPx,
int layoutStatusIconHeightSteps, int layoutStatusIconHeightSteps,
int layoutStatusLockIconHeightSteps, int layoutStatusLockIconHeightSteps,
@@ -535,17 +473,14 @@ public final class SbtSettings {
int layoutStatusUnlockedCount, int layoutStatusUnlockedCount,
String[] layoutStatusPositions, String[] layoutStatusPositions,
String[] layoutStatusMiddleSides, String[] layoutStatusMiddleSides,
boolean[] layoutStatusMiddleAutoNearestSides,
int[] layoutStatusVerticalOffsetsPx, int[] layoutStatusVerticalOffsetsPx,
int layoutStatusLockCount, int layoutStatusLockCount,
String[] layoutStatusLockPositions, String[] layoutStatusLockPositions,
String[] layoutStatusLockMiddleSides, String[] layoutStatusLockMiddleSides,
boolean[] layoutStatusLockMiddleAutoNearestSides,
int[] layoutStatusLockVerticalOffsetsPx, int[] layoutStatusLockVerticalOffsetsPx,
int layoutStatusAodCount, int layoutStatusAodCount,
String[] layoutStatusAodPositions, String[] layoutStatusAodPositions,
String[] layoutStatusAodMiddleSides, String[] layoutStatusAodMiddleSides,
boolean[] layoutStatusAodMiddleAutoNearestSides,
int[] layoutStatusAodVerticalOffsetsPx, int[] layoutStatusAodVerticalOffsetsPx,
Map<String, String> clockCameraTypeOverrides, Map<String, String> clockCameraTypeOverrides,
Map<String, Integer> systemIconBlockedModes, Map<String, Integer> systemIconBlockedModes,
@@ -671,7 +606,6 @@ public final class SbtSettings {
this.layoutCarrierMiddleSide = layoutCarrierMiddleSide != null this.layoutCarrierMiddleSide = layoutCarrierMiddleSide != null
? layoutCarrierMiddleSide ? layoutCarrierMiddleSide
: SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT; : SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT;
this.layoutCarrierMiddleAutoNearestSide = layoutCarrierMiddleAutoNearestSide;
this.layoutCarrierVerticalOffsetPx = clampInt( this.layoutCarrierVerticalOffsetPx = clampInt(
layoutCarrierVerticalOffsetPx, layoutCarrierVerticalOffsetPx,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -679,12 +613,10 @@ public final class SbtSettings {
this.layoutChipPosition = layoutChipPosition != null this.layoutChipPosition = layoutChipPosition != null
? layoutChipPosition ? layoutChipPosition
: SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT; : SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT;
this.layoutChipEnabledLockscreen = layoutChipEnabledLockscreen;
this.layoutChipEnabledUnlocked = layoutChipEnabledUnlocked; this.layoutChipEnabledUnlocked = layoutChipEnabledUnlocked;
this.layoutChipMiddleSide = layoutChipMiddleSide != null this.layoutChipMiddleSide = layoutChipMiddleSide != null
? layoutChipMiddleSide ? layoutChipMiddleSide
: SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT; : SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT;
this.layoutChipMiddleAutoNearestSide = layoutChipMiddleAutoNearestSide;
this.layoutChipVerticalOffsetPx = clampInt( this.layoutChipVerticalOffsetPx = clampInt(
layoutChipVerticalOffsetPx, layoutChipVerticalOffsetPx,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -696,14 +628,12 @@ public final class SbtSettings {
this.layoutNotifSortOrder = layoutNotifSortOrder != null this.layoutNotifSortOrder = layoutNotifSortOrder != null
? layoutNotifSortOrder ? layoutNotifSortOrder
: SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT; : SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT;
this.layoutNotifShowDotIfTruncated = layoutNotifShowDotIfTruncated;
this.layoutNotifEnabledAod = layoutNotifEnabledAod; this.layoutNotifEnabledAod = layoutNotifEnabledAod;
this.layoutNotifEnabledLockscreen = layoutNotifEnabledLockscreen; this.layoutNotifEnabledLockscreen = layoutNotifEnabledLockscreen;
this.layoutNotifEnabledUnlocked = layoutNotifEnabledUnlocked; this.layoutNotifEnabledUnlocked = layoutNotifEnabledUnlocked;
this.layoutNotifMiddleSide = layoutNotifMiddleSide != null this.layoutNotifMiddleSide = layoutNotifMiddleSide != null
? layoutNotifMiddleSide ? layoutNotifMiddleSide
: SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT; : SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT;
this.layoutNotifMiddleAutoNearestSide = layoutNotifMiddleAutoNearestSide;
this.layoutNotifVerticalOffsetPx = clampInt( this.layoutNotifVerticalOffsetPx = clampInt(
layoutNotifVerticalOffsetPx, layoutNotifVerticalOffsetPx,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -720,10 +650,6 @@ public final class SbtSettings {
layoutNotifMiddleSides, layoutNotifMiddleSides,
this.layoutNotifMiddleSide, this.layoutNotifMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifMiddleAutoNearestSides = sanitizeBooleanArray(
layoutNotifMiddleAutoNearestSides,
this.layoutNotifMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifVerticalOffsetsPx = sanitizeIntArray( this.layoutNotifVerticalOffsetsPx = sanitizeIntArray(
layoutNotifVerticalOffsetsPx, layoutNotifVerticalOffsetsPx,
this.layoutNotifVerticalOffsetPx, this.layoutNotifVerticalOffsetPx,
@@ -739,10 +665,6 @@ public final class SbtSettings {
layoutNotifLockMiddleSides, layoutNotifLockMiddleSides,
this.layoutNotifMiddleSide, this.layoutNotifMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifLockMiddleAutoNearestSides = sanitizeBooleanArray(
layoutNotifLockMiddleAutoNearestSides,
this.layoutNotifMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifLockVerticalOffsetsPx = sanitizeIntArray( this.layoutNotifLockVerticalOffsetsPx = sanitizeIntArray(
layoutNotifLockVerticalOffsetsPx, layoutNotifLockVerticalOffsetsPx,
this.layoutNotifVerticalOffsetPx, this.layoutNotifVerticalOffsetPx,
@@ -758,10 +680,6 @@ public final class SbtSettings {
layoutNotifAodMiddleSides, layoutNotifAodMiddleSides,
this.layoutNotifMiddleSide, this.layoutNotifMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifAodMiddleAutoNearestSides = sanitizeBooleanArray(
layoutNotifAodMiddleAutoNearestSides,
this.layoutNotifMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutNotifAodVerticalOffsetsPx = sanitizeIntArray( this.layoutNotifAodVerticalOffsetsPx = sanitizeIntArray(
layoutNotifAodVerticalOffsetsPx, layoutNotifAodVerticalOffsetsPx,
this.layoutNotifVerticalOffsetPx, this.layoutNotifVerticalOffsetPx,
@@ -774,11 +692,9 @@ public final class SbtSettings {
this.layoutStatusEnabledAod = layoutStatusEnabledAod; this.layoutStatusEnabledAod = layoutStatusEnabledAod;
this.layoutStatusEnabledLockscreen = layoutStatusEnabledLockscreen; this.layoutStatusEnabledLockscreen = layoutStatusEnabledLockscreen;
this.layoutStatusEnabledUnlocked = layoutStatusEnabledUnlocked; this.layoutStatusEnabledUnlocked = layoutStatusEnabledUnlocked;
this.layoutStatusShowDotIfTruncated = layoutStatusShowDotIfTruncated;
this.layoutStatusMiddleSide = layoutStatusMiddleSide != null this.layoutStatusMiddleSide = layoutStatusMiddleSide != null
? layoutStatusMiddleSide ? layoutStatusMiddleSide
: SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT; : SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT;
this.layoutStatusMiddleAutoNearestSide = layoutStatusMiddleAutoNearestSide;
this.layoutStatusVerticalOffsetPx = clampInt( this.layoutStatusVerticalOffsetPx = clampInt(
layoutStatusVerticalOffsetPx, layoutStatusVerticalOffsetPx,
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -795,10 +711,6 @@ public final class SbtSettings {
layoutStatusMiddleSides, layoutStatusMiddleSides,
this.layoutStatusMiddleSide, this.layoutStatusMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusMiddleAutoNearestSides = sanitizeBooleanArray(
layoutStatusMiddleAutoNearestSides,
this.layoutStatusMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusVerticalOffsetsPx = sanitizeIntArray( this.layoutStatusVerticalOffsetsPx = sanitizeIntArray(
layoutStatusVerticalOffsetsPx, layoutStatusVerticalOffsetsPx,
this.layoutStatusVerticalOffsetPx, this.layoutStatusVerticalOffsetPx,
@@ -814,10 +726,6 @@ public final class SbtSettings {
layoutStatusLockMiddleSides, layoutStatusLockMiddleSides,
this.layoutStatusMiddleSide, this.layoutStatusMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusLockMiddleAutoNearestSides = sanitizeBooleanArray(
layoutStatusLockMiddleAutoNearestSides,
this.layoutStatusMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusLockVerticalOffsetsPx = sanitizeIntArray( this.layoutStatusLockVerticalOffsetsPx = sanitizeIntArray(
layoutStatusLockVerticalOffsetsPx, layoutStatusLockVerticalOffsetsPx,
this.layoutStatusVerticalOffsetPx, this.layoutStatusVerticalOffsetPx,
@@ -833,10 +741,6 @@ public final class SbtSettings {
layoutStatusAodMiddleSides, layoutStatusAodMiddleSides,
this.layoutStatusMiddleSide, this.layoutStatusMiddleSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX); SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusAodMiddleAutoNearestSides = sanitizeBooleanArray(
layoutStatusAodMiddleAutoNearestSides,
this.layoutStatusMiddleAutoNearestSide,
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
this.layoutStatusAodVerticalOffsetsPx = sanitizeIntArray( this.layoutStatusAodVerticalOffsetsPx = sanitizeIntArray(
layoutStatusAodVerticalOffsetsPx, layoutStatusAodVerticalOffsetsPx,
this.layoutStatusVerticalOffsetPx, this.layoutStatusVerticalOffsetPx,
@@ -936,23 +840,18 @@ public final class SbtSettings {
SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT,
SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT,
SbtDefaults.LAYOUT_CHIP_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT, SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
@@ -961,24 +860,19 @@ public final class SbtSettings {
null, null,
null, null,
null, null,
null,
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
null, null,
null, null,
null, null,
null,
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
null, null,
null, null,
null, null,
null,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT,
@@ -987,17 +881,14 @@ public final class SbtSettings {
null, null,
null, null,
null, null,
null,
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
null, null,
null, null,
null, null,
null,
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
null, null,
null, null,
null, null,
null,
Collections.emptyMap(), Collections.emptyMap(),
Collections.emptyMap(), Collections.emptyMap(),
false, false,
@@ -1208,13 +1099,10 @@ public final class SbtSettings {
prefs.getString(KEY_LAYOUT_CARRIER_POSITION, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT), prefs.getString(KEY_LAYOUT_CARRIER_POSITION, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT), prefs.getBoolean(KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT),
prefs.getString(KEY_LAYOUT_CARRIER_MIDDLE_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT), prefs.getString(KEY_LAYOUT_CARRIER_MIDDLE_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
prefs.getInt(KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT), prefs.getInt(KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT),
prefs.getString(KEY_LAYOUT_CHIP_POSITION, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT), prefs.getString(KEY_LAYOUT_CHIP_POSITION, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_CHIP_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CHIP_ENABLED_LOCKSCREEN_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT), prefs.getBoolean(KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT),
prefs.getString(KEY_LAYOUT_CHIP_MIDDLE_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT), prefs.getString(KEY_LAYOUT_CHIP_MIDDLE_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(prefs.getInt(KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX, clampInt(prefs.getInt(KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1223,12 +1111,10 @@ public final class SbtSettings {
SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT)), SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT)),
prefs.getString(KEY_LAYOUT_NOTIF_POSITION, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT), prefs.getString(KEY_LAYOUT_NOTIF_POSITION, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT),
prefs.getString(KEY_LAYOUT_NOTIF_SORT_ORDER, SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT), prefs.getString(KEY_LAYOUT_NOTIF_SORT_ORDER, SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_AOD, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT), prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_AOD, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT), prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT), prefs.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT),
prefs.getString(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), prefs.getString(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(prefs.getInt(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, clampInt(prefs.getInt(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1259,10 +1145,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutNotifMiddleSideKey, SbtSettings::layoutNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutNotifVerticalOffsetKey, SbtSettings::layoutNotifVerticalOffsetKey,
@@ -1281,10 +1163,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutLockNotifMiddleSideKey, SbtSettings::layoutLockNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutLockNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutLockNotifVerticalOffsetKey, SbtSettings::layoutLockNotifVerticalOffsetKey,
@@ -1303,10 +1181,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutAodNotifMiddleSideKey, SbtSettings::layoutAodNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutAodNotifVerticalOffsetKey, SbtSettings::layoutAodNotifVerticalOffsetKey,
@@ -1315,9 +1189,7 @@ public final class SbtSettings {
prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_AOD, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT), prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_AOD, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT), prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT), prefs.getBoolean(KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED_DEFAULT),
prefs.getString(KEY_LAYOUT_STATUS_MIDDLE_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), prefs.getString(KEY_LAYOUT_STATUS_MIDDLE_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
prefs.getBoolean(KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(prefs.getInt(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, clampInt(prefs.getInt(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1348,10 +1220,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutStatusMiddleSideKey, SbtSettings::layoutStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutStatusVerticalOffsetKey, SbtSettings::layoutStatusVerticalOffsetKey,
@@ -1370,10 +1238,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutLockStatusMiddleSideKey, SbtSettings::layoutLockStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutLockStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutLockStatusVerticalOffsetKey, SbtSettings::layoutLockStatusVerticalOffsetKey,
@@ -1392,10 +1256,6 @@ public final class SbtSettings {
prefs, prefs,
SbtSettings::layoutAodStatusMiddleSideKey, SbtSettings::layoutAodStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromPrefs(
prefs,
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromPrefs( readIntArrayFromPrefs(
prefs, prefs,
SbtSettings::layoutAodStatusVerticalOffsetKey, SbtSettings::layoutAodStatusVerticalOffsetKey,
@@ -1537,13 +1397,10 @@ public final class SbtSettings {
bundle.getString(KEY_LAYOUT_CARRIER_POSITION, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT), bundle.getString(KEY_LAYOUT_CARRIER_POSITION, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT), bundle.getBoolean(KEY_LAYOUT_CARRIER_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CARRIER_ENABLED_LOCKSCREEN_DEFAULT),
bundle.getString(KEY_LAYOUT_CARRIER_MIDDLE_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT), bundle.getString(KEY_LAYOUT_CARRIER_MIDDLE_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
bundle.getInt(KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT), bundle.getInt(KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT),
bundle.getString(KEY_LAYOUT_CHIP_POSITION, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT), bundle.getString(KEY_LAYOUT_CHIP_POSITION, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_CHIP_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_CHIP_ENABLED_LOCKSCREEN_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT), bundle.getBoolean(KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT),
bundle.getString(KEY_LAYOUT_CHIP_MIDDLE_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT), bundle.getString(KEY_LAYOUT_CHIP_MIDDLE_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(bundle.getInt(KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX, clampInt(bundle.getInt(KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1552,12 +1409,10 @@ public final class SbtSettings {
SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT)), SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT)),
bundle.getString(KEY_LAYOUT_NOTIF_POSITION, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT), bundle.getString(KEY_LAYOUT_NOTIF_POSITION, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT),
bundle.getString(KEY_LAYOUT_NOTIF_SORT_ORDER, SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT), bundle.getString(KEY_LAYOUT_NOTIF_SORT_ORDER, SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_AOD, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT), bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_AOD, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT), bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT), bundle.getBoolean(KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT),
bundle.getString(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), bundle.getString(KEY_LAYOUT_NOTIF_MIDDLE_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(bundle.getInt(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, clampInt(bundle.getInt(KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1588,10 +1443,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutNotifMiddleSideKey, SbtSettings::layoutNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutNotifVerticalOffsetKey, SbtSettings::layoutNotifVerticalOffsetKey,
@@ -1610,10 +1461,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutLockNotifMiddleSideKey, SbtSettings::layoutLockNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutLockNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutLockNotifVerticalOffsetKey, SbtSettings::layoutLockNotifVerticalOffsetKey,
@@ -1632,10 +1479,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutAodNotifMiddleSideKey, SbtSettings::layoutAodNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutAodNotifVerticalOffsetKey, SbtSettings::layoutAodNotifVerticalOffsetKey,
@@ -1644,9 +1487,7 @@ public final class SbtSettings {
bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_AOD, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT), bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_AOD, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT), bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT), bundle.getBoolean(KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED_DEFAULT),
bundle.getString(KEY_LAYOUT_STATUS_MIDDLE_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), bundle.getString(KEY_LAYOUT_STATUS_MIDDLE_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
bundle.getBoolean(KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE, SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
clampInt(bundle.getInt(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, clampInt(bundle.getInt(KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT), SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN, SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
@@ -1677,10 +1518,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutStatusMiddleSideKey, SbtSettings::layoutStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutStatusVerticalOffsetKey, SbtSettings::layoutStatusVerticalOffsetKey,
@@ -1699,10 +1536,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutLockStatusMiddleSideKey, SbtSettings::layoutLockStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutLockStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutLockStatusVerticalOffsetKey, SbtSettings::layoutLockStatusVerticalOffsetKey,
@@ -1721,10 +1554,6 @@ public final class SbtSettings {
bundle, bundle,
SbtSettings::layoutAodStatusMiddleSideKey, SbtSettings::layoutAodStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT), SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
readBooleanArrayFromBundle(
bundle,
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
readIntArrayFromBundle( readIntArrayFromBundle(
bundle, bundle,
SbtSettings::layoutAodStatusVerticalOffsetKey, SbtSettings::layoutAodStatusVerticalOffsetKey,
@@ -1829,20 +1658,6 @@ public final class SbtSettings {
return result; return result;
} }
private static boolean[] readBooleanArrayFromPrefs(
SharedPreferences prefs,
IndexedKey key,
boolean fallback
) {
boolean[] result = new boolean[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX];
boolean previous = fallback;
for (int i = 0; i < result.length; i++) {
previous = prefs.contains(key.key(i)) ? prefs.getBoolean(key.key(i), previous) : previous;
result[i] = previous;
}
return result;
}
private static int[] readIntArrayFromPrefs(SharedPreferences prefs, IndexedKey key, int fallback) { private static int[] readIntArrayFromPrefs(SharedPreferences prefs, IndexedKey key, int fallback) {
int[] result = new int[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX]; int[] result = new int[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX];
int previous = fallback; int previous = fallback;
@@ -1863,16 +1678,6 @@ public final class SbtSettings {
return result; return result;
} }
private static boolean[] readBooleanArrayFromBundle(Bundle bundle, IndexedKey key, boolean fallback) {
boolean[] result = new boolean[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX];
boolean previous = fallback;
for (int i = 0; i < result.length; i++) {
previous = bundle.containsKey(key.key(i)) ? bundle.getBoolean(key.key(i), previous) : previous;
result[i] = previous;
}
return result;
}
private static int[] readIntArrayFromBundle(Bundle bundle, IndexedKey key, int fallback) { private static int[] readIntArrayFromBundle(Bundle bundle, IndexedKey key, int fallback) {
int[] result = new int[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX]; int[] result = new int[SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX];
int previous = fallback; int previous = fallback;
@@ -1892,14 +1697,6 @@ public final class SbtSettings {
return result; return result;
} }
private static boolean[] sanitizeBooleanArray(boolean[] source, boolean fallback, int length) {
boolean[] result = new boolean[Math.max(0, length)];
for (int i = 0; i < result.length; i++) {
result[i] = source != null && i < source.length ? source[i] : fallback;
}
return result;
}
private static int[] sanitizeIntArray(int[] source, int fallback, int length, int min, int max) { private static int[] sanitizeIntArray(int[] source, int fallback, int length, int min, int max) {
int[] result = new int[Math.max(0, length)]; int[] result = new int[Math.max(0, length)];
for (int i = 0; i < result.length; i++) { for (int i = 0; i < result.length; i++) {
@@ -195,27 +195,18 @@ public class SbtSettingsProvider extends ContentProvider {
out.putString(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE, out.putString(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE,
prefs.getString(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE, prefs.getString(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT)); SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT));
out.putInt(SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, out.putInt(SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX,
prefs.getInt(SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, prefs.getInt(SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT)); SbtDefaults.LAYOUT_CARRIER_VERTICAL_OFFSET_PX_DEFAULT));
out.putString(SbtSettings.KEY_LAYOUT_CHIP_POSITION, out.putString(SbtSettings.KEY_LAYOUT_CHIP_POSITION,
prefs.getString(SbtSettings.KEY_LAYOUT_CHIP_POSITION, prefs.getString(SbtSettings.KEY_LAYOUT_CHIP_POSITION,
SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT)); SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_LOCKSCREEN,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_LOCKSCREEN,
SbtDefaults.LAYOUT_CHIP_ENABLED_LOCKSCREEN_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, out.putBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_UNLOCKED,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_UNLOCKED, prefs.getBoolean(SbtSettings.KEY_LAYOUT_CHIP_ENABLED_UNLOCKED,
SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT)); SbtDefaults.LAYOUT_CHIP_ENABLED_UNLOCKED_DEFAULT));
out.putString(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE, out.putString(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE,
prefs.getString(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE, prefs.getString(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE,
SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT)); SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE,
SbtDefaults.LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT));
out.putInt(SbtSettings.KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX, out.putInt(SbtSettings.KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX,
prefs.getInt(SbtSettings.KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX, prefs.getInt(SbtSettings.KEY_LAYOUT_CHIP_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT)); SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT));
@@ -228,9 +219,6 @@ public class SbtSettingsProvider extends ContentProvider {
out.putString(SbtSettings.KEY_LAYOUT_NOTIF_SORT_ORDER, out.putString(SbtSettings.KEY_LAYOUT_NOTIF_SORT_ORDER,
prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_SORT_ORDER, prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_SORT_ORDER,
SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT)); SbtDefaults.LAYOUT_NOTIF_SORT_ORDER_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED,
SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD, out.putBoolean(SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD, prefs.getBoolean(SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD,
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT)); SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT));
@@ -250,9 +238,6 @@ public class SbtSettingsProvider extends ContentProvider {
out.putString(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE, out.putString(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE,
prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE, prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT)); SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT));
out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
prefs.getInt(SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, prefs.getInt(SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT)); SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT));
@@ -266,8 +251,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtSettings::layoutNotifMiddleSideKey, SbtSettings::layoutNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutNotifVerticalOffsetKey, SbtSettings::layoutNotifVerticalOffsetKey,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT);
out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_LOCK_COUNT, out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_LOCK_COUNT,
@@ -287,8 +270,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtSettings::layoutLockNotifMiddleSideKey, SbtSettings::layoutLockNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutLockNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutLockNotifVerticalOffsetKey, SbtSettings::layoutLockNotifVerticalOffsetKey,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT);
out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_AOD_COUNT, out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_AOD_COUNT,
@@ -308,8 +289,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtSettings::layoutAodNotifMiddleSideKey, SbtSettings::layoutAodNotifMiddleSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutAodNotifVerticalOffsetKey, SbtSettings::layoutAodNotifVerticalOffsetKey,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT);
out.putString(SbtSettings.KEY_LAYOUT_STATUS_POSITION, out.putString(SbtSettings.KEY_LAYOUT_STATUS_POSITION,
@@ -331,15 +310,9 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT) SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT)
? SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT ? SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT
: 0)); : 0));
out.putBoolean(SbtSettings.KEY_LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED,
SbtDefaults.LAYOUT_STATUS_SHOW_DOT_IF_TRUNCATED_DEFAULT));
out.putString(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE, out.putString(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE,
prefs.getString(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE, prefs.getString(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT)); SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT));
out.putBoolean(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE,
prefs.getBoolean(SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT));
out.putInt(SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, out.putInt(SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
prefs.getInt(SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, prefs.getInt(SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT)); SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT));
@@ -353,8 +326,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtSettings::layoutStatusMiddleSideKey, SbtSettings::layoutStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutStatusVerticalOffsetKey, SbtSettings::layoutStatusVerticalOffsetKey,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT);
out.putInt(SbtSettings.KEY_LAYOUT_STATUS_LOCK_COUNT, out.putInt(SbtSettings.KEY_LAYOUT_STATUS_LOCK_COUNT,
@@ -374,8 +345,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtSettings::layoutLockStatusMiddleSideKey, SbtSettings::layoutLockStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutLockStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutLockStatusVerticalOffsetKey, SbtSettings::layoutLockStatusVerticalOffsetKey,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT);
out.putInt(SbtSettings.KEY_LAYOUT_STATUS_AOD_COUNT, out.putInt(SbtSettings.KEY_LAYOUT_STATUS_AOD_COUNT,
@@ -395,8 +364,6 @@ public class SbtSettingsProvider extends ContentProvider {
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtSettings::layoutAodStatusMiddleSideKey, SbtSettings::layoutAodStatusMiddleSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtSettings::layoutAodStatusVerticalOffsetKey, SbtSettings::layoutAodStatusVerticalOffsetKey,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT); SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT);
putStringSetArrayList(out, prefs, SbtSettings.KEY_CLOCK_CAMERA_TYPE_OVERRIDES); putStringSetArrayList(out, prefs, SbtSettings.KEY_CLOCK_CAMERA_TYPE_OVERRIDES);
@@ -465,14 +432,11 @@ public class SbtSettingsProvider extends ContentProvider {
String positionDefault, String positionDefault,
SbtSettings.IndexedKey middleSideKey, SbtSettings.IndexedKey middleSideKey,
String middleSideDefault, String middleSideDefault,
SbtSettings.IndexedKey autoNearestKey,
boolean autoNearestDefault,
SbtSettings.IndexedKey verticalOffsetKey, SbtSettings.IndexedKey verticalOffsetKey,
int verticalOffsetDefault int verticalOffsetDefault
) { ) {
String position = positionDefault; String position = positionDefault;
String middleSide = middleSideDefault; String middleSide = middleSideDefault;
boolean autoNearest = autoNearestDefault;
int verticalOffset = verticalOffsetDefault; int verticalOffset = verticalOffsetDefault;
for (int i = 0; i < SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX; i++) { for (int i = 0; i < SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX; i++) {
position = prefs.contains(positionKey.key(i)) position = prefs.contains(positionKey.key(i))
@@ -481,15 +445,11 @@ public class SbtSettingsProvider extends ContentProvider {
middleSide = prefs.contains(middleSideKey.key(i)) middleSide = prefs.contains(middleSideKey.key(i))
? prefs.getString(middleSideKey.key(i), middleSide) ? prefs.getString(middleSideKey.key(i), middleSide)
: middleSide; : middleSide;
autoNearest = prefs.contains(autoNearestKey.key(i))
? prefs.getBoolean(autoNearestKey.key(i), autoNearest)
: autoNearest;
verticalOffset = prefs.contains(verticalOffsetKey.key(i)) verticalOffset = prefs.contains(verticalOffsetKey.key(i))
? prefs.getInt(verticalOffsetKey.key(i), verticalOffset) ? prefs.getInt(verticalOffsetKey.key(i), verticalOffset)
: verticalOffset; : verticalOffset;
out.putString(positionKey.key(i), position); out.putString(positionKey.key(i), position);
out.putString(middleSideKey.key(i), middleSide); out.putString(middleSideKey.key(i), middleSide);
out.putBoolean(autoNearestKey.key(i), autoNearest);
out.putInt(verticalOffsetKey.key(i), verticalOffset); out.putInt(verticalOffsetKey.key(i), verticalOffset);
} }
} }
@@ -56,31 +56,31 @@ public final class LayoutFragment extends Fragment {
prefs, prefs,
R.id.notif_position_group, R.id.notif_position_group,
R.id.notif_position_middle_options_container, R.id.notif_position_middle_options_container,
R.id.notif_middle_auto_nearest, View.NO_ID,
R.id.notif_middle_side_prompt, R.id.notif_middle_side_prompt,
SbtSettings.KEY_LAYOUT_NOTIF_POSITION, SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE, null,
SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE); SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE);
setupPositionSection(root, setupPositionSection(root,
prefs, prefs,
R.id.chip_position_group, R.id.chip_position_group,
R.id.chip_position_middle_options_container, R.id.chip_position_middle_options_container,
R.id.chip_middle_auto_nearest, View.NO_ID,
R.id.chip_middle_side_prompt, R.id.chip_middle_side_prompt,
SbtSettings.KEY_LAYOUT_CHIP_POSITION, SbtSettings.KEY_LAYOUT_CHIP_POSITION,
SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT, SbtDefaults.LAYOUT_CHIP_POSITION_DEFAULT,
SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_SIDE, null,
SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE); SbtSettings.KEY_LAYOUT_CHIP_MIDDLE_SIDE);
setupPositionSection(root, setupPositionSection(root,
prefs, prefs,
R.id.status_position_group, R.id.status_position_group,
R.id.status_position_middle_options_container, R.id.status_position_middle_options_container,
R.id.status_middle_auto_nearest, View.NO_ID,
R.id.status_middle_side_prompt, R.id.status_middle_side_prompt,
SbtSettings.KEY_LAYOUT_STATUS_POSITION, SbtSettings.KEY_LAYOUT_STATUS_POSITION,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE, null,
SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE); SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE);
bindStepper(prefs, bindStepper(prefs,
@@ -150,12 +150,10 @@ public final class LayoutFragment extends Fragment {
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED,
SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT,
SbtSettings::layoutNotifPositionKey, SbtSettings::layoutNotifPositionKey,
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
SbtSettings::layoutNotifMiddleSideKey, SbtSettings::layoutNotifMiddleSideKey,
SbtSettings::layoutNotifVerticalOffsetKey, SbtSettings::layoutNotifVerticalOffsetKey,
SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS, SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT,
@@ -170,12 +168,10 @@ public final class LayoutFragment extends Fragment {
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED,
SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT,
SbtSettings::layoutStatusPositionKey, SbtSettings::layoutStatusPositionKey,
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
SbtSettings::layoutStatusMiddleSideKey, SbtSettings::layoutStatusMiddleSideKey,
SbtSettings::layoutStatusVerticalOffsetKey, SbtSettings::layoutStatusVerticalOffsetKey,
SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS, SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT, SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT,
@@ -193,12 +189,10 @@ public final class LayoutFragment extends Fragment {
String legacyEnabledKey, String legacyEnabledKey,
boolean legacyEnabledDefault, boolean legacyEnabledDefault,
SbtSettings.IndexedKey positionKey, SbtSettings.IndexedKey positionKey,
SbtSettings.IndexedKey autoNearestKey,
SbtSettings.IndexedKey middleSideKey, SbtSettings.IndexedKey middleSideKey,
SbtSettings.IndexedKey verticalOffsetKey, SbtSettings.IndexedKey verticalOffsetKey,
String iconHeightKey, String iconHeightKey,
String positionDefault, String positionDefault,
boolean autoNearestDefault,
String middleSideDefault, String middleSideDefault,
int verticalOffsetDefault, int verticalOffsetDefault,
int iconHeightDefault, int iconHeightDefault,
@@ -225,7 +219,12 @@ public final class LayoutFragment extends Fragment {
rebuild[0] = () -> { rebuild[0] = () -> {
countContainer.removeAllViews(); countContainer.removeAllViews();
removeGeneratedCopyCards(cardsParent, copyTag); removeGeneratedCopyCards(cardsParent, copyTag);
int count = iconContainerCount(prefs, countKey, countDefault, legacyEnabledKey, legacyEnabledDefault); int count = ViewTreeSupport.iconContainerCount(
prefs,
countKey,
legacyEnabledKey,
countDefault,
legacyEnabledDefault);
LayoutXmlCardSupport.setIndexedCardTitle(requireContext(), sourceCard, sectionTitleId, 0, count); LayoutXmlCardSupport.setIndexedCardTitle(requireContext(), sourceCard, sectionTitleId, 0, count);
boolean cardsMode = LockedNotificationModeUi.MODE_CARDS.equals( boolean cardsMode = LockedNotificationModeUi.MODE_CARDS.equals(
LockedNotificationModeUi.currentMode(requireContext())); LockedNotificationModeUi.currentMode(requireContext()));
@@ -238,11 +237,15 @@ public final class LayoutFragment extends Fragment {
cardsMode, cardsMode,
0, 0,
this::refreshSelf); this::refreshSelf);
countContainer.addView(iconContainerCountControl( countContainer.addView(ViewTreeSupport.iconContainerCountControl(
requireContext(),
count,
value -> ViewTreeSupport.persistIconContainerCount(
requireContext(),
prefs, prefs,
countKey, countKey,
count,
legacyEnabledKey, legacyEnabledKey,
value),
() -> { () -> {
if (rebuild[0] != null) { if (rebuild[0] != null) {
rebuild[0].run(); rebuild[0].run();
@@ -264,11 +267,9 @@ public final class LayoutFragment extends Fragment {
sectionTitleId, sectionTitleId,
i, i,
positionKey, positionKey,
autoNearestKey,
middleSideKey, middleSideKey,
verticalOffsetKey, verticalOffsetKey,
positionDefault, positionDefault,
autoNearestDefault,
middleSideDefault, middleSideDefault,
verticalOffsetDefault, verticalOffsetDefault,
copyTag); copyTag);
@@ -294,105 +295,28 @@ public final class LayoutFragment extends Fragment {
}); });
} }
private View iconContainerCountControl(
SharedPreferences prefs,
String countKey,
int current,
String legacyEnabledKey,
Runnable onChanged
) {
Context context = requireContext();
LinearLayout outer = ViewTreeSupport.verticalLayout(context);
TextView label = ViewTreeSupport.bodyText(context, R.string.layout_icon_container_count, 0);
outer.addView(label);
LinearLayout row = new LinearLayout(context);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setGravity(android.view.Gravity.CENTER_VERTICAL);
MaterialButton minus = ViewTreeSupport.outlinedStepperButton(context, "-");
MaterialButton plus = ViewTreeSupport.outlinedStepperButton(context, "+");
EditText input = ViewTreeSupport.numericInput(context, false, 1);
input.setText(String.valueOf(current));
row.addView(minus, ViewTreeSupport.stepperButtonParams(context));
row.addView(input, ViewTreeSupport.stepperInputParams(context));
row.addView(plus, ViewTreeSupport.stepperButtonParams(context));
outer.addView(row);
View.OnClickListener listener = view -> {
int next = SbtSettings.clampIconContainerCount(
ViewTreeSupport.parseInt(input, current) + (view == minus ? -1 : 1));
persistIconContainerCount(prefs, countKey, legacyEnabledKey, next);
onChanged.run();
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = SbtSettings.clampIconContainerCount(ViewTreeSupport.parseInt(input, current));
persistIconContainerCount(prefs, countKey, legacyEnabledKey, next);
onChanged.run();
}
});
return outer;
}
private View iconHeightControl( private View iconHeightControl(
SharedPreferences prefs, SharedPreferences prefs,
String key, String key,
int defaultValue, int defaultValue,
int labelRes int labelRes
) { ) {
Context context = requireContext(); return ViewTreeSupport.intPreferenceStepper(
LinearLayout outer = ViewTreeSupport.verticalLayout(context); requireContext(),
TextView label = ViewTreeSupport.bodyText(context, labelRes, 0); prefs,
outer.addView(label); labelRes,
key,
LinearLayout row = new LinearLayout(context); defaultValue,
row.setOrientation(LinearLayout.HORIZONTAL); SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
row.setGravity(android.view.Gravity.CENTER_VERTICAL); SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX,
MaterialButton minus = ViewTreeSupport.outlinedStepperButton(context, "-"); false,
MaterialButton plus = ViewTreeSupport.outlinedStepperButton(context, "+"); 3,
MaterialButton reset = ViewTreeSupport.outlinedStepperButton(context, "D"); 0,
EditText input = ViewTreeSupport.numericInput(context, false, 3); 0,
int current = SbtSettings.clampIconHeightSteps(prefs.getInt(key, defaultValue)); 0,
input.setText(String.valueOf(current)); true,
row.addView(minus, ViewTreeSupport.stepperButtonParams(context)); true,
row.addView(input, ViewTreeSupport.stepperInputParams(context)); null);
row.addView(plus, ViewTreeSupport.stepperButtonParams(context));
LinearLayout.LayoutParams resetParams = ViewTreeSupport.stepperButtonParams(context);
resetParams.leftMargin = ViewTreeSupport.dp(context, 8);
row.addView(reset, resetParams);
outer.addView(row);
View.OnClickListener listener = view -> {
int next = SbtSettings.clampIconHeightSteps(
ViewTreeSupport.parseInt(input, current) + (view == minus ? -1 : 1));
persistIconHeight(prefs, key, input, next);
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
reset.setOnClickListener(v -> {
int next = SbtSettings.clampIconHeightSteps(defaultValue);
persistIconHeight(prefs, key, input, next);
});
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = SbtSettings.clampIconHeightSteps(ViewTreeSupport.parseInt(input, current));
persistIconHeight(prefs, key, input, next);
}
});
return outer;
}
private void persistIconHeight(
SharedPreferences prefs,
String key,
EditText input,
int value
) {
prefs.edit().putInt(key, value).apply();
SbtSettings.ensureReadable(requireContext());
input.setText(String.valueOf(value));
} }
private void addChipHeightControl(View root, SharedPreferences prefs) { private void addChipHeightControl(View root, SharedPreferences prefs) {
@@ -424,11 +348,9 @@ public final class LayoutFragment extends Fragment {
int titleId, int titleId,
int index, int index,
SbtSettings.IndexedKey positionKey, SbtSettings.IndexedKey positionKey,
SbtSettings.IndexedKey autoNearestKey,
SbtSettings.IndexedKey middleSideKey, SbtSettings.IndexedKey middleSideKey,
SbtSettings.IndexedKey verticalOffsetKey, SbtSettings.IndexedKey verticalOffsetKey,
String positionDefault, String positionDefault,
boolean autoNearestDefault,
String middleSideDefault, String middleSideDefault,
int verticalOffsetDefault, int verticalOffsetDefault,
String copyTag String copyTag
@@ -447,11 +369,11 @@ public final class LayoutFragment extends Fragment {
prefs, prefs,
R.id.notif_position_group, R.id.notif_position_group,
R.id.notif_position_middle_options_container, R.id.notif_position_middle_options_container,
R.id.notif_middle_auto_nearest, View.NO_ID,
R.id.notif_middle_side_prompt, R.id.notif_middle_side_prompt,
positionKey.key(index), positionKey.key(index),
positionDefault, positionDefault,
autoNearestKey.key(index), null,
middleSideKey.key(index)); middleSideKey.key(index));
bindStepper(prefs, bindStepper(prefs,
verticalOffsetKey.key(index), verticalOffsetKey.key(index),
@@ -467,11 +389,11 @@ public final class LayoutFragment extends Fragment {
prefs, prefs,
R.id.status_position_group, R.id.status_position_group,
R.id.status_position_middle_options_container, R.id.status_position_middle_options_container,
R.id.status_middle_auto_nearest, View.NO_ID,
R.id.status_middle_side_prompt, R.id.status_middle_side_prompt,
positionKey.key(index), positionKey.key(index),
positionDefault, positionDefault,
autoNearestKey.key(index), null,
middleSideKey.key(index)); middleSideKey.key(index));
bindStepper(prefs, bindStepper(prefs,
verticalOffsetKey.key(index), verticalOffsetKey.key(index),
@@ -563,30 +485,6 @@ public final class LayoutFragment extends Fragment {
} }
} }
private int iconContainerCount(
SharedPreferences prefs,
String countKey,
int countDefault,
String legacyEnabledKey,
boolean legacyEnabledDefault
) {
int fallback = prefs.getBoolean(legacyEnabledKey, legacyEnabledDefault) ? countDefault : 0;
return SbtSettings.clampIconContainerCount(prefs.getInt(countKey, fallback));
}
private void persistIconContainerCount(
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
int count
) {
prefs.edit()
.putInt(countKey, SbtSettings.clampIconContainerCount(count))
.putBoolean(legacyEnabledKey, count > 0)
.apply();
SbtSettings.ensureReadable(requireContext());
}
private void hideUnlockedSubpageObsoleteControls(View root) { private void hideUnlockedSubpageObsoleteControls(View root) {
hide(root, R.id.clock_position_mode_lockscreen); hide(root, R.id.clock_position_mode_lockscreen);
hide(root, R.id.notif_position_mode_aod); hide(root, R.id.notif_position_mode_aod);
@@ -620,43 +518,42 @@ public final class LayoutFragment extends Fragment {
int middleOptionsId, int middleOptionsId,
int autoNearestId, int autoNearestId,
int promptId, int promptId,
@Nullable String positionKey, String positionKey,
@Nullable String positionDefault, String positionDefault,
@Nullable String autoNearestKey, @Nullable String autoNearestKey,
@Nullable String middleSideKey) { String middleSideKey) {
RadioGroup group = root.findViewById(groupId); RadioGroup group = root.findViewById(groupId);
View middleOptions = root.findViewById(middleOptionsId); View middleOptions = root.findViewById(middleOptionsId);
CheckBox autoNearest = root.findViewById(autoNearestId); CheckBox autoNearest = root.findViewById(autoNearestId);
TextView prompt = root.findViewById(promptId); TextView prompt = root.findViewById(promptId);
if (group == null || middleOptions == null || autoNearest == null || prompt == null) { if (group == null || middleOptions == null || prompt == null) {
return; return;
} }
if (positionKey != null && positionDefault != null) {
group.check(positionIdForValue(groupId, prefs.getString(positionKey, positionDefault))); group.check(positionIdForValue(groupId, prefs.getString(positionKey, positionDefault)));
} boolean autoNearestAvailable = autoNearestKey != null && autoNearest != null;
if (autoNearestKey != null) { if (autoNearestAvailable) {
autoNearest.setChecked(prefs.getBoolean(autoNearestKey, true)); autoNearest.setChecked(prefs.getBoolean(autoNearestKey, true));
} else if (autoNearest != null) {
autoNearest.setChecked(false);
autoNearest.setVisibility(View.GONE);
} }
updateMiddleOptions(middleOptions, autoNearest, prompt, group.getCheckedRadioButtonId()); updateMiddleOptions(middleOptions, autoNearest, prompt, group.getCheckedRadioButtonId());
group.setOnCheckedChangeListener((radioGroup, id) -> { group.setOnCheckedChangeListener((radioGroup, id) -> {
updateMiddleOptions(middleOptions, autoNearest, prompt, id); updateMiddleOptions(middleOptions, autoNearest, prompt, id);
if (positionKey != null) {
prefs.edit().putString(positionKey, positionValueForId(id)).apply(); prefs.edit().putString(positionKey, positionValueForId(id)).apply();
SbtSettings.ensureReadable(requireContext()); SbtSettings.ensureReadable(requireContext());
}
}); });
if (autoNearestAvailable) {
autoNearest.setOnCheckedChangeListener((buttonView, isChecked) -> { autoNearest.setOnCheckedChangeListener((buttonView, isChecked) -> {
updateMiddlePrompt(prompt, isChecked); updateMiddlePrompt(prompt, isChecked);
if (autoNearestKey != null) {
prefs.edit().putBoolean(autoNearestKey, isChecked).apply(); prefs.edit().putBoolean(autoNearestKey, isChecked).apply();
SbtSettings.ensureReadable(requireContext()); SbtSettings.ensureReadable(requireContext());
}
}); });
}
if (middleSideKey != null) {
RadioGroup sideGroup = resolveMiddleSideGroup(root, groupId); RadioGroup sideGroup = resolveMiddleSideGroup(root, groupId);
if (sideGroup != null) { if (sideGroup != null) {
sideGroup.check(sideIdForValue(sideGroup, prefs.getString(middleSideKey, "left"))); sideGroup.check(sideIdForValue(sideGroup, prefs.getString(middleSideKey, "left")));
@@ -666,13 +563,12 @@ public final class LayoutFragment extends Fragment {
}); });
} }
} }
}
private void updateMiddleOptions(View middleOptions, private void updateMiddleOptions(View middleOptions,
CheckBox autoNearest, @Nullable CheckBox autoNearest,
TextView prompt, TextView prompt,
int checkedId) { int checkedId) {
if (middleOptions == null || autoNearest == null || prompt == null) { if (middleOptions == null || prompt == null) {
return; return;
} }
if (middleOptions.getVisibility() != View.VISIBLE) { if (middleOptions.getVisibility() != View.VISIBLE) {
@@ -681,7 +577,7 @@ public final class LayoutFragment extends Fragment {
boolean enabled = isMiddleSelection(checkedId); boolean enabled = isMiddleSelection(checkedId);
ViewTreeSupport.setEnabledRecursive(middleOptions, enabled); ViewTreeSupport.setEnabledRecursive(middleOptions, enabled);
middleOptions.setAlpha(enabled ? 1f : 0.45f); middleOptions.setAlpha(enabled ? 1f : 0.45f);
updateMiddlePrompt(prompt, autoNearest.isChecked()); updateMiddlePrompt(prompt, autoNearest != null && autoNearest.isChecked());
} }
private boolean isMiddleSelection(int checkedId) { private boolean isMiddleSelection(int checkedId) {
@@ -700,37 +596,6 @@ public final class LayoutFragment extends Fragment {
: R.string.layout_middle_side_prompt_attach_only); : R.string.layout_middle_side_prompt_attach_only);
} }
private void bindStepper(SharedPreferences prefs,
@Nullable String key,
@Nullable EditText input,
@Nullable MaterialButton minusButton,
@Nullable MaterialButton plusButton,
int initialValue) {
bindStepper(prefs, key, input, null, minusButton, plusButton, null, null, initialValue);
}
private void bindStepper(SharedPreferences prefs,
@Nullable String key,
@Nullable EditText input,
@Nullable MaterialButton minusButton,
@Nullable MaterialButton plusButton,
int initialValue,
int minValue,
int maxValue) {
bindStepper(
prefs,
key,
input,
null,
minusButton,
plusButton,
null,
null,
initialValue,
minValue,
maxValue);
}
private void bindStepper(SharedPreferences prefs, private void bindStepper(SharedPreferences prefs,
@Nullable String key, @Nullable String key,
@Nullable EditText input, @Nullable EditText input,
@@ -880,8 +745,7 @@ public final class LayoutFragment extends Fragment {
if (key == null) { if (key == null) {
return; return;
} }
prefs.edit().putInt(key, value).apply(); ViewTreeSupport.persistIntPreference(requireContext(), prefs, key, value);
SbtSettings.ensureReadable(requireContext());
} }
private int positionIdForValue(int groupId, @Nullable String value) { private int positionIdForValue(int groupId, @Nullable String value) {
@@ -6,7 +6,6 @@ import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.RadioGroup; import android.widget.RadioGroup;
import android.widget.ScrollView; import android.widget.ScrollView;
@@ -16,7 +15,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.button.MaterialButton;
import com.google.android.material.switchmaterial.SwitchMaterial; import com.google.android.material.switchmaterial.SwitchMaterial;
import se.ajpanton.statusbartweak.R; import se.ajpanton.statusbartweak.R;
@@ -38,7 +36,7 @@ public final class LayoutHomeFragment extends Fragment {
Context context = requireContext(); Context context = requireContext();
SharedPreferences prefs = context.getSharedPreferences(SbtSettings.PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences prefs = context.getSharedPreferences(SbtSettings.PREFS_NAME, Context.MODE_PRIVATE);
ScrollView scroll = new ScrollView(context); ScrollView scroll = new ScrollView(context);
LinearLayout root = vertical(context); LinearLayout root = ViewTreeSupport.verticalLayout(context);
root.setPadding( root.setPadding(
ViewTreeSupport.dp(context, 20), ViewTreeSupport.dp(context, 20),
ViewTreeSupport.dp(context, 20), ViewTreeSupport.dp(context, 20),
@@ -46,23 +44,23 @@ public final class LayoutHomeFragment extends Fragment {
ViewTreeSupport.dp(context, 20)); ViewTreeSupport.dp(context, 20));
scroll.addView(root); scroll.addView(root);
TextView title = title(context, R.string.layout_home_title); TextView title = ViewTreeSupport.titleText(context, R.string.layout_home_title);
root.addView(title); root.addView(title);
SwitchMaterial master = new SwitchMaterial(context); SwitchMaterial master = new SwitchMaterial(context);
master.setText(R.string.layout_enabled); master.setText(R.string.layout_enabled);
master.setChecked(prefs.getBoolean(SbtSettings.KEY_CLOCK_ENABLED, SbtDefaults.CLOCK_ENABLED_DEFAULT)); master.setChecked(prefs.getBoolean(SbtSettings.KEY_CLOCK_ENABLED, SbtDefaults.CLOCK_ENABLED_DEFAULT));
root.addView(card(context, R.string.layout_master_toggle_title, master)); root.addView(outlinedCard(context, R.string.layout_master_toggle_title, master));
lockedModeGroup = new RadioGroup(context); lockedModeGroup = new RadioGroup(context);
lockedModeGroup.setOrientation(RadioGroup.VERTICAL); lockedModeGroup.setOrientation(RadioGroup.VERTICAL);
lockedModeHint = body(context, R.string.layout_locked_notifications_hint); lockedModeHint = ViewTreeSupport.bodyText(context, R.string.layout_locked_notifications_hint, 0);
LinearLayout lockedContent = vertical(context); LinearLayout lockedContent = ViewTreeSupport.verticalLayout(context);
lockedContent.addView(lockedModeHint); lockedContent.addView(lockedModeHint);
lockedContent.addView(lockedModeGroup); lockedContent.addView(lockedModeGroup);
root.addView(card(context, R.string.layout_locked_notifications_title, lockedContent)); root.addView(outlinedCard(context, R.string.layout_locked_notifications_title, lockedContent));
layoutOnContainer = vertical(context); layoutOnContainer = ViewTreeSupport.verticalLayout(context);
layoutOnContainer.addView(paddingCard(context, prefs)); layoutOnContainer.addView(paddingCard(context, prefs));
layoutOnContainer.addView(LayoutOrderingUi.createCard(context, prefs)); layoutOnContainer.addView(LayoutOrderingUi.createCard(context, prefs));
root.addView(layoutOnContainer); root.addView(layoutOnContainer);
@@ -94,7 +92,7 @@ public final class LayoutHomeFragment extends Fragment {
} }
private View paddingCard(Context context, SharedPreferences prefs) { private View paddingCard(Context context, SharedPreferences prefs) {
LinearLayout content = vertical(context); LinearLayout content = ViewTreeSupport.verticalLayout(context);
content.addView(stepper( content.addView(stepper(
context, context,
prefs, prefs,
@@ -141,12 +139,12 @@ public final class LayoutHomeFragment extends Fragment {
SbtDefaults.LAYOUT_ITEM_PADDING_PX_DEFAULT, SbtDefaults.LAYOUT_ITEM_PADDING_PX_DEFAULT,
SbtDefaults.LAYOUT_ITEM_PADDING_PX_MIN, SbtDefaults.LAYOUT_ITEM_PADDING_PX_MIN,
SbtDefaults.LAYOUT_ITEM_PADDING_PX_MAX)); SbtDefaults.LAYOUT_ITEM_PADDING_PX_MAX));
return card(context, R.string.layout_padding_title, content); return outlinedCard(context, R.string.layout_padding_title, content);
} }
private View miscCard(Context context, SharedPreferences prefs) { private View miscCard(Context context, SharedPreferences prefs) {
LinearLayout content = vertical(context); LinearLayout content = ViewTreeSupport.verticalLayout(context);
miscLayoutOnContainer = vertical(context); miscLayoutOnContainer = ViewTreeSupport.verticalLayout(context);
miscLayoutOnContainer.addView(ViewTreeSupport.boundCheckBox( miscLayoutOnContainer.addView(ViewTreeSupport.boundCheckBox(
context, context,
prefs, prefs,
@@ -155,7 +153,7 @@ public final class LayoutHomeFragment extends Fragment {
SbtDefaults.LAYOUT_IGNORE_UNDER_DISPLAY_CAMERAS_DEFAULT, SbtDefaults.LAYOUT_IGNORE_UNDER_DISPLAY_CAMERAS_DEFAULT,
false)); false));
content.addView(miscLayoutOnContainer); content.addView(miscLayoutOnContainer);
miscUnlockedOffOnlyContainer = vertical(context); miscUnlockedOffOnlyContainer = ViewTreeSupport.verticalLayout(context);
miscUnlockedOffOnlyContainer.addView(stepper( miscUnlockedOffOnlyContainer.addView(stepper(
context, context,
prefs, prefs,
@@ -165,7 +163,7 @@ public final class LayoutHomeFragment extends Fragment {
SbtDefaults.UNLOCKED_MAX_ICONS_PER_ROW_MIN, SbtDefaults.UNLOCKED_MAX_ICONS_PER_ROW_MIN,
SbtDefaults.UNLOCKED_MAX_ICONS_PER_ROW_MAX)); SbtDefaults.UNLOCKED_MAX_ICONS_PER_ROW_MAX));
content.addView(miscUnlockedOffOnlyContainer); content.addView(miscUnlockedOffOnlyContainer);
return card(context, R.string.layout_misc_title, content); return outlinedCard(context, R.string.layout_misc_title, content);
} }
private View stepper( private View stepper(
@@ -190,65 +188,28 @@ public final class LayoutHomeFragment extends Fragment {
int max, int max,
@Nullable View trailingView @Nullable View trailingView
) { ) {
LinearLayout outer = vertical(context); return ViewTreeSupport.intPreferenceStepper(
TextView label = body(context, labelId); context,
outer.addView(label); prefs,
LinearLayout row = new LinearLayout(context); labelId,
row.setOrientation(LinearLayout.HORIZONTAL); key,
row.setGravity(android.view.Gravity.CENTER_VERTICAL); defaultValue,
row.setPadding(0, ViewTreeSupport.dp(context, 6), 0, ViewTreeSupport.dp(context, 8)); min,
MaterialButton minus = ViewTreeSupport.outlinedStepperButton(context, "-"); max,
MaterialButton plus = ViewTreeSupport.outlinedStepperButton(context, "+"); true,
EditText input = ViewTreeSupport.numericInput(context, true, 5); 5,
input.setText(String.valueOf(ViewTreeSupport.clamp(prefs.getInt(key, defaultValue), min, max))); 0,
row.addView(minus, ViewTreeSupport.stepperButtonParams(context)); 6,
row.addView(input, ViewTreeSupport.stepperInputParams(context)); 8,
row.addView(plus, ViewTreeSupport.stepperButtonParams(context)); false,
if (trailingView != null) { false,
LinearLayout.LayoutParams trailingParams = new LinearLayout.LayoutParams( trailingView);
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
trailingParams.leftMargin = ViewTreeSupport.dp(context, 8);
row.addView(trailingView, trailingParams);
}
outer.addView(row);
View.OnClickListener listener = v -> {
int delta = v == minus ? -1 : 1;
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, defaultValue) + delta, min, max);
input.setText(String.valueOf(next));
prefs.edit().putInt(key, next).apply();
SbtSettings.ensureReadable(context);
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, defaultValue), min, max);
input.setText(String.valueOf(next));
prefs.edit().putInt(key, next).apply();
SbtSettings.ensureReadable(context);
}
});
return outer;
} }
private View card(Context context, int titleId, View content) { private View outlinedCard(Context context, int titleId, View content) {
return ViewTreeSupport.outlinedCard(context, sectionTitle(context, titleId), content); return ViewTreeSupport.outlinedCard(
} context,
ViewTreeSupport.sectionTitleText(context, titleId, true),
private LinearLayout vertical(Context context) { content);
return ViewTreeSupport.verticalLayout(context);
}
private TextView title(Context context, int stringId) {
return ViewTreeSupport.titleText(context, stringId);
}
private TextView sectionTitle(Context context, int stringId) {
return ViewTreeSupport.sectionTitleText(context, stringId, true);
}
private TextView body(Context context, int stringId) {
return ViewTreeSupport.bodyText(context, stringId, 0);
} }
} }
@@ -30,8 +30,8 @@ final class LayoutOrderingUi {
} }
static View createCard(Context context, SharedPreferences prefs) { static View createCard(Context context, SharedPreferences prefs) {
LinearLayout content = vertical(context); LinearLayout content = ViewTreeSupport.verticalLayout(context);
TextView hint = body(context, R.string.layout_ordering_hint); TextView hint = bodyText(context, R.string.layout_ordering_hint);
content.addView(hint); content.addView(hint);
RecyclerView list = new RecyclerView(context); RecyclerView list = new RecyclerView(context);
@@ -43,7 +43,7 @@ final class LayoutOrderingUi {
content.addView(list, listParams); content.addView(list, listParams);
bindOrderingList(context, prefs, list); bindOrderingList(context, prefs, list);
TextView sortTitle = body(context, R.string.layout_sort_icons_title); TextView sortTitle = bodyText(context, R.string.layout_sort_icons_title);
sortTitle.setTypeface(sortTitle.getTypeface(), android.graphics.Typeface.BOLD); sortTitle.setTypeface(sortTitle.getTypeface(), android.graphics.Typeface.BOLD);
LinearLayout.LayoutParams sortTitleParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams sortTitleParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@@ -71,7 +71,10 @@ final class LayoutOrderingUi {
sortParams.topMargin = ViewTreeSupport.dp(context, 8); sortParams.topMargin = ViewTreeSupport.dp(context, 8);
content.addView(sortGroup, sortParams); content.addView(sortGroup, sortParams);
return card(context, R.string.layout_ordering_title, content); return ViewTreeSupport.outlinedCard(
context,
ViewTreeSupport.sectionTitleText(context, R.string.layout_ordering_title, true),
content);
} }
static ArrayList<String> orderedKeys(SharedPreferences prefs) { static ArrayList<String> orderedKeys(SharedPreferences prefs) {
@@ -225,18 +228,7 @@ final class LayoutOrderingUi {
return tag instanceof String value ? value : "automatic"; return tag instanceof String value ? value : "automatic";
} }
private static View card(Context context, int titleId, View content) { private static TextView bodyText(Context context, int stringId) {
return ViewTreeSupport.outlinedCard(
context,
ViewTreeSupport.sectionTitleText(context, titleId, true),
content);
}
private static LinearLayout vertical(Context context) {
return ViewTreeSupport.verticalLayout(context);
}
private static TextView body(Context context, int stringId) {
TextView view = new TextView(context); TextView view = new TextView(context);
view.setText(stringId); view.setText(stringId);
view.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Body2); view.setTextAppearance(com.google.android.material.R.style.TextAppearance_MaterialComponents_Body2);
@@ -197,7 +197,6 @@ final class LayoutSectionCopySupport {
copyInt(editor, prefs, src.iconHeight, dst.iconHeight, src.iconHeightDefault); copyInt(editor, prefs, src.iconHeight, dst.iconHeight, src.iconHeightDefault);
for (int i = 0; i < MAX_COPIES; i++) { for (int i = 0; i < MAX_COPIES; i++) {
copyString(editor, prefs, src.positionAt(i), dst.positionAt(i), src.positionDefault); copyString(editor, prefs, src.positionAt(i), dst.positionAt(i), src.positionDefault);
copyBoolean(editor, prefs, src.autoNearestAt(i), dst.autoNearestAt(i), src.autoNearestDefault);
copyString(editor, prefs, src.middleSideAt(i), dst.middleSideAt(i), src.middleSideDefault); copyString(editor, prefs, src.middleSideAt(i), dst.middleSideAt(i), src.middleSideDefault);
copyInt(editor, prefs, src.verticalOffsetAt(i), dst.verticalOffsetAt(i), src.verticalOffsetDefault); copyInt(editor, prefs, src.verticalOffsetAt(i), dst.verticalOffsetAt(i), src.verticalOffsetDefault);
} }
@@ -276,14 +275,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN,
SbtSettings.KEY_LAYOUT_NOTIF_LOCK_COUNT, SbtSettings.KEY_LAYOUT_NOTIF_LOCK_COUNT,
SbtSettings.KEY_LAYOUT_NOTIF_LOCK_POSITION, SbtSettings.KEY_LAYOUT_NOTIF_LOCK_POSITION,
SbtSettings.KEY_LAYOUT_NOTIF_LOCK_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_NOTIF_LOCK_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_NOTIF_LOCK_VERTICAL_OFFSET_PX,
SbtSettings.layoutLockNotifIconHeightKey(), SbtSettings.layoutLockNotifIconHeightKey(),
SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT);
@@ -293,14 +290,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD, SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD,
SbtSettings.KEY_LAYOUT_NOTIF_AOD_COUNT, SbtSettings.KEY_LAYOUT_NOTIF_AOD_COUNT,
SbtSettings.KEY_LAYOUT_NOTIF_AOD_POSITION, SbtSettings.KEY_LAYOUT_NOTIF_AOD_POSITION,
SbtSettings.KEY_LAYOUT_NOTIF_AOD_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_NOTIF_AOD_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_NOTIF_AOD_VERTICAL_OFFSET_PX,
SbtSettings.layoutAodNotifIconHeightKey(), SbtSettings.layoutAodNotifIconHeightKey(),
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT);
@@ -309,14 +304,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED, SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED,
SbtSettings.KEY_LAYOUT_NOTIF_UNLOCKED_COUNT, SbtSettings.KEY_LAYOUT_NOTIF_UNLOCKED_COUNT,
SbtSettings.KEY_LAYOUT_NOTIF_POSITION, SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_NOTIF_VERTICAL_OFFSET_PX,
SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS, SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_NOTIF_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT);
@@ -328,14 +321,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, SbtSettings.KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN,
SbtSettings.KEY_LAYOUT_STATUS_LOCK_COUNT, SbtSettings.KEY_LAYOUT_STATUS_LOCK_COUNT,
SbtSettings.KEY_LAYOUT_STATUS_LOCK_POSITION, SbtSettings.KEY_LAYOUT_STATUS_LOCK_POSITION,
SbtSettings.KEY_LAYOUT_STATUS_LOCK_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_STATUS_LOCK_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_STATUS_LOCK_VERTICAL_OFFSET_PX,
SbtSettings.layoutLockStatusIconHeightKey(), SbtSettings.layoutLockStatusIconHeightKey(),
SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT);
@@ -345,14 +336,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_AOD, SbtSettings.KEY_LAYOUT_STATUS_ENABLED_AOD,
SbtSettings.KEY_LAYOUT_STATUS_AOD_COUNT, SbtSettings.KEY_LAYOUT_STATUS_AOD_COUNT,
SbtSettings.KEY_LAYOUT_STATUS_AOD_POSITION, SbtSettings.KEY_LAYOUT_STATUS_AOD_POSITION,
SbtSettings.KEY_LAYOUT_STATUS_AOD_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_STATUS_AOD_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_STATUS_AOD_VERTICAL_OFFSET_PX,
SbtSettings.layoutAodStatusIconHeightKey(), SbtSettings.layoutAodStatusIconHeightKey(),
SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT,
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT);
@@ -361,14 +350,12 @@ final class LayoutSectionCopySupport {
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED, SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED,
SbtSettings.KEY_LAYOUT_STATUS_UNLOCKED_COUNT, SbtSettings.KEY_LAYOUT_STATUS_UNLOCKED_COUNT,
SbtSettings.KEY_LAYOUT_STATUS_POSITION, SbtSettings.KEY_LAYOUT_STATUS_POSITION,
SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_SIDE,
SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS, SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT, SbtDefaults.LAYOUT_STATUS_ENABLED_UNLOCKED_DEFAULT,
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT, SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT); SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT);
@@ -405,14 +392,12 @@ final class LayoutSectionCopySupport {
String enabled, String enabled,
String count, String count,
String position, String position,
String autoNearest,
String middleSide, String middleSide,
String verticalOffset, String verticalOffset,
String iconHeight, String iconHeight,
boolean enabledDefault, boolean enabledDefault,
int countDefault, int countDefault,
String positionDefault, String positionDefault,
boolean autoNearestDefault,
String middleSideDefault, String middleSideDefault,
int verticalOffsetDefault, int verticalOffsetDefault,
int iconHeightDefault int iconHeightDefault
@@ -420,14 +405,14 @@ final class LayoutSectionCopySupport {
return new KeySet( return new KeySet(
enabled, enabled,
position, position,
autoNearest, null,
middleSide, middleSide,
verticalOffset, verticalOffset,
iconHeight, iconHeight,
count, count,
enabledDefault, enabledDefault,
positionDefault, positionDefault,
autoNearestDefault, false,
middleSideDefault, middleSideDefault,
verticalOffsetDefault, verticalOffsetDefault,
iconHeightDefault, iconHeightDefault,
@@ -701,10 +686,6 @@ final class LayoutSectionCopySupport {
return suffixed(position, index); return suffixed(position, index);
} }
String autoNearestAt(int index) {
return suffixed(autoNearest, index);
}
String middleSideAt(int index) { String middleSideAt(int index) {
return suffixed(middleSide, index); return suffixed(middleSide, index);
} }
@@ -4,7 +4,6 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.text.InputFilter; import android.text.InputFilter;
import android.view.Gravity;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -20,6 +19,7 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import se.ajpanton.statusbartweak.R; import se.ajpanton.statusbartweak.R;
@@ -44,7 +44,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
Context context = requireContext(); Context context = requireContext();
SharedPreferences prefs = context.getSharedPreferences(SbtSettings.PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences prefs = context.getSharedPreferences(SbtSettings.PREFS_NAME, Context.MODE_PRIVATE);
ScrollView scroll = new ScrollView(context); ScrollView scroll = new ScrollView(context);
LinearLayout root = vertical(context); LinearLayout root = ViewTreeSupport.verticalLayout(context);
root.setPadding( root.setPadding(
ViewTreeSupport.dp(context, 20), ViewTreeSupport.dp(context, 20),
ViewTreeSupport.dp(context, 20), ViewTreeSupport.dp(context, 20),
@@ -52,16 +52,18 @@ abstract class LockedSceneLayoutFragment extends Fragment {
ViewTreeSupport.dp(context, 20)); ViewTreeSupport.dp(context, 20));
scroll.addView(root); scroll.addView(root);
root.addView(title(context, aod ? R.string.section_aod : R.string.section_lockscreen)); root.addView(ViewTreeSupport.titleText(
context,
aod ? R.string.section_aod : R.string.section_lockscreen));
modeGroup = new RadioGroup(context); modeGroup = new RadioGroup(context);
modeGroup.setOrientation(RadioGroup.VERTICAL); modeGroup.setOrientation(RadioGroup.VERTICAL);
modeHint = body(context, R.string.layout_locked_notifications_hint); modeHint = ViewTreeSupport.bodyText(context, R.string.layout_locked_notifications_hint, 6);
LinearLayout modeContent = vertical(context); LinearLayout modeContent = ViewTreeSupport.verticalLayout(context);
modeContent.addView(modeHint); modeContent.addView(modeHint);
modeContent.addView(modeGroup); modeContent.addView(modeGroup);
root.addView(card(context, R.string.layout_locked_notifications_title, modeContent)); root.addView(outlinedCard(context, R.string.layout_locked_notifications_title, modeContent));
dynamicContent = vertical(context); dynamicContent = ViewTreeSupport.verticalLayout(context);
root.addView(dynamicContent); root.addView(dynamicContent);
bindMode(context, prefs); bindMode(context, prefs);
return scroll; return scroll;
@@ -142,8 +144,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
R.id.clock_vertical_offset_reset, R.id.clock_vertical_offset_reset,
SbtSettings.KEY_LAYOUT_CARRIER_POSITION, SbtSettings.KEY_LAYOUT_CARRIER_POSITION,
SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT, SbtDefaults.LAYOUT_CARRIER_POSITION_DEFAULT,
SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE, null,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT, false,
SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE, SbtSettings.KEY_LAYOUT_CARRIER_MIDDLE_SIDE,
SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_CARRIER_MIDDLE_SIDE_DEFAULT,
SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX, SbtSettings.KEY_LAYOUT_CARRIER_VERTICAL_OFFSET_PX,
@@ -159,7 +161,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
aod ? R.id.status_position_mode_aod : R.id.status_position_mode_lockscreen, aod ? R.id.status_position_mode_aod : R.id.status_position_mode_lockscreen,
R.id.status_position_group, R.id.status_position_group,
R.id.status_position_middle_options_container, R.id.status_position_middle_options_container,
R.id.status_middle_auto_nearest, View.NO_ID,
R.id.status_middle_side_prompt, R.id.status_middle_side_prompt,
R.id.status_middle_side_group, R.id.status_middle_side_group,
R.id.status_middle_side_right, R.id.status_middle_side_right,
@@ -173,7 +175,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
aod ? SbtSettings.KEY_LAYOUT_STATUS_ENABLED_AOD : SbtSettings.KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN, aod ? SbtSettings.KEY_LAYOUT_STATUS_ENABLED_AOD : SbtSettings.KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN,
aod ? SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT : SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT, aod ? SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT : SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT,
aod ? SbtSettings.layoutAodStatusIconHeightKey() : SbtSettings.layoutLockStatusIconHeightKey(), aod ? SbtSettings.layoutAodStatusIconHeightKey() : SbtSettings.layoutLockStatusIconHeightKey(),
@@ -192,7 +193,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
aod ? R.id.notif_position_mode_aod : R.id.notif_position_mode_lockscreen, aod ? R.id.notif_position_mode_aod : R.id.notif_position_mode_lockscreen,
R.id.notif_position_group, R.id.notif_position_group,
R.id.notif_position_middle_options_container, R.id.notif_position_middle_options_container,
R.id.notif_middle_auto_nearest, View.NO_ID,
R.id.notif_middle_side_prompt, R.id.notif_middle_side_prompt,
R.id.notif_middle_side_group, R.id.notif_middle_side_group,
R.id.notif_middle_side_right, R.id.notif_middle_side_right,
@@ -206,7 +207,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
aod ? SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD : SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN, aod ? SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD : SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_LOCKSCREEN,
aod ? SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT : SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT, aod ? SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT : SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT, SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT, SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT, SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT,
aod ? SbtSettings.layoutAodNotifIconHeightKey() : SbtSettings.layoutLockNotifIconHeightKey(), aod ? SbtSettings.layoutAodNotifIconHeightKey() : SbtSettings.layoutLockNotifIconHeightKey(),
@@ -307,7 +307,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
String legacyEnabledKey, String legacyEnabledKey,
boolean legacyEnabledDefault, boolean legacyEnabledDefault,
String positionDefault, String positionDefault,
boolean autoNearestDefault,
String middleSideDefault, String middleSideDefault,
int verticalOffsetDefault, int verticalOffsetDefault,
String iconHeightKey, String iconHeightKey,
@@ -316,12 +315,17 @@ abstract class LockedSceneLayoutFragment extends Fragment {
boolean cardsMode, boolean cardsMode,
@Nullable Runnable refresh @Nullable Runnable refresh
) { ) {
LinearLayout wrapper = vertical(context); LinearLayout wrapper = ViewTreeSupport.verticalLayout(context);
String countKey = sceneKey(base + "_count"); String countKey = sceneKey(base + "_count");
Runnable[] rebuild = new Runnable[1]; Runnable[] rebuild = new Runnable[1];
rebuild[0] = () -> { rebuild[0] = () -> {
wrapper.removeAllViews(); wrapper.removeAllViews();
int count = iconContainerCount(prefs, countKey, legacyEnabledKey, legacyEnabledDefault); int count = ViewTreeSupport.iconContainerCount(
prefs,
countKey,
legacyEnabledKey,
1,
legacyEnabledDefault);
View primary = configuredIconContainerCard( View primary = configuredIconContainerCard(
context, context,
prefs, prefs,
@@ -343,8 +347,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
0, 0,
indexedSceneKey(base + "_position", 0), indexedSceneKey(base + "_position", 0),
positionDefault, positionDefault,
indexedSceneKey(base + "_middle_auto_nearest_side", 0),
autoNearestDefault,
indexedSceneKey(base + "_middle_side", 0), indexedSceneKey(base + "_middle_side", 0),
middleSideDefault, middleSideDefault,
indexedSceneKey(base + "_vertical_offset_px", 0), indexedSceneKey(base + "_vertical_offset_px", 0),
@@ -379,8 +381,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
i, i,
indexedSceneKey(base + "_position", i), indexedSceneKey(base + "_position", i),
positionDefault, positionDefault,
indexedSceneKey(base + "_middle_auto_nearest_side", i),
autoNearestDefault,
indexedSceneKey(base + "_middle_side", i), indexedSceneKey(base + "_middle_side", i),
middleSideDefault, middleSideDefault,
indexedSceneKey(base + "_vertical_offset_px", i), indexedSceneKey(base + "_vertical_offset_px", i),
@@ -441,8 +441,6 @@ abstract class LockedSceneLayoutFragment extends Fragment {
int index, int index,
String positionKey, String positionKey,
String positionDefault, String positionDefault,
String autoNearestKey,
boolean autoNearestDefault,
String middleSideKey, String middleSideKey,
String middleSideDefault, String middleSideDefault,
String verticalOffsetKey, String verticalOffsetKey,
@@ -460,7 +458,16 @@ abstract class LockedSceneLayoutFragment extends Fragment {
if (sectionContent != null && countKey != null && onCountChanged != null) { if (sectionContent != null && countKey != null && onCountChanged != null) {
int insertIndex = Math.min(1, sectionContent.getChildCount()); int insertIndex = Math.min(1, sectionContent.getChildCount());
sectionContent.addView( sectionContent.addView(
iconContainerCountControl(context, prefs, countKey, legacyEnabledKey, count, onCountChanged), ViewTreeSupport.iconContainerCountControl(
context,
count,
value -> ViewTreeSupport.persistIconContainerCount(
context,
prefs,
countKey,
legacyEnabledKey,
value),
onCountChanged),
insertIndex); insertIndex);
if (iconHeightKey != null) { if (iconHeightKey != null) {
sectionContent.addView( sectionContent.addView(
@@ -487,8 +494,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
middleSideRightId, middleSideRightId,
positionKey, positionKey,
positionDefault, positionDefault,
autoNearestKey, null,
autoNearestDefault, false,
middleSideKey, middleSideKey,
middleSideDefault); middleSideDefault);
bindXmlStepper( bindXmlStepper(
@@ -544,7 +551,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
} }
private View cardsNotificationCard(Context context, SharedPreferences prefs, @Nullable Runnable refresh) { private View cardsNotificationCard(Context context, SharedPreferences prefs, @Nullable Runnable refresh) {
LinearLayout content = vertical(context); LinearLayout content = ViewTreeSupport.verticalLayout(context);
LayoutSectionCopySupport.addCardsDropdown(context, prefs, content, copyMode(), refresh); LayoutSectionCopySupport.addCardsDropdown(context, prefs, content, copyMode(), refresh);
content.addView(stepper( content.addView(stepper(
context, context,
@@ -586,48 +593,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
: SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT, : SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN, SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX)); SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX));
return card(context, R.string.layout_notification_position_title, content); return outlinedCard(context, R.string.layout_notification_position_title, content);
}
private View iconContainerCountControl(
Context context,
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
int current,
Runnable onChanged
) {
LinearLayout outer = vertical(context);
outer.addView(body(context, R.string.layout_icon_container_count));
LinearLayout row = new LinearLayout(context);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setGravity(Gravity.CENTER_VERTICAL);
MaterialButton minus = ViewTreeSupport.outlinedStepperButton(context, "-");
MaterialButton plus = ViewTreeSupport.outlinedStepperButton(context, "+");
EditText input = ViewTreeSupport.numericInput(context, false, 4);
input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(1)});
input.setText(String.valueOf(current));
row.addView(minus, ViewTreeSupport.stepperButtonParams(context));
row.addView(input, ViewTreeSupport.stepperInputParams(context));
row.addView(plus, ViewTreeSupport.stepperButtonParams(context));
outer.addView(row);
View.OnClickListener listener = view -> {
int next = SbtSettings.clampIconContainerCount(
ViewTreeSupport.parseInt(input, current) + (view == minus ? -1 : 1));
persistIconContainerCount(prefs, countKey, legacyEnabledKey, next);
onChanged.run();
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = SbtSettings.clampIconContainerCount(ViewTreeSupport.parseInt(input, current));
persistIconContainerCount(prefs, countKey, legacyEnabledKey, next);
onChanged.run();
}
});
return outer;
} }
private void bindXmlPositionSection( private void bindXmlPositionSection(
@@ -641,7 +607,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
int middleSideRightId, int middleSideRightId,
String positionKey, String positionKey,
String positionDefault, String positionDefault,
String autoNearestKey, @Nullable String autoNearestKey,
boolean autoNearestDefault, boolean autoNearestDefault,
String middleSideKey, String middleSideKey,
String middleSideDefault String middleSideDefault
@@ -651,17 +617,23 @@ abstract class LockedSceneLayoutFragment extends Fragment {
CheckBox autoNearest = root.findViewById(autoNearestId); CheckBox autoNearest = root.findViewById(autoNearestId);
TextView prompt = root.findViewById(promptId); TextView prompt = root.findViewById(promptId);
RadioGroup side = root.findViewById(middleSideGroupId); RadioGroup side = root.findViewById(middleSideGroupId);
if (position == null || middleOptions == null || autoNearest == null || prompt == null || side == null) { if (position == null || middleOptions == null || prompt == null || side == null) {
return; return;
} }
position.check(positionIdForValue(groupId, prefs.getString(positionKey, positionDefault))); position.check(positionIdForValue(groupId, prefs.getString(positionKey, positionDefault)));
boolean autoNearestAvailable = autoNearestKey != null && autoNearest != null;
if (autoNearestAvailable) {
autoNearest.setChecked(prefs.getBoolean(autoNearestKey, autoNearestDefault)); autoNearest.setChecked(prefs.getBoolean(autoNearestKey, autoNearestDefault));
} else if (autoNearest != null) {
autoNearest.setChecked(false);
autoNearest.setVisibility(View.GONE);
}
side.check("right".equals(prefs.getString(middleSideKey, middleSideDefault)) side.check("right".equals(prefs.getString(middleSideKey, middleSideDefault))
? middleSideRightId ? middleSideRightId
: firstSideId(side, middleSideRightId)); : firstSideId(side, middleSideRightId));
updateMiddleOptions(middleOptions, "middle".equals(positionValueForId(position.getCheckedRadioButtonId()))); updateMiddleOptions(middleOptions, "middle".equals(positionValueForId(position.getCheckedRadioButtonId())));
prompt.setText(autoNearest.isChecked() prompt.setText(autoNearest != null && autoNearest.isChecked()
? R.string.layout_middle_side_prompt_centred ? R.string.layout_middle_side_prompt_centred
: R.string.layout_middle_side_prompt_attach_only); : R.string.layout_middle_side_prompt_attach_only);
@@ -670,6 +642,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
updateMiddleOptions(middleOptions, "middle".equals(positionValueForId(checkedId))); updateMiddleOptions(middleOptions, "middle".equals(positionValueForId(checkedId)));
SbtSettings.ensureReadable(requireContext()); SbtSettings.ensureReadable(requireContext());
}); });
if (autoNearestAvailable) {
autoNearest.setOnCheckedChangeListener((buttonView, isChecked) -> { autoNearest.setOnCheckedChangeListener((buttonView, isChecked) -> {
prefs.edit().putBoolean(autoNearestKey, isChecked).apply(); prefs.edit().putBoolean(autoNearestKey, isChecked).apply();
prompt.setText(isChecked prompt.setText(isChecked
@@ -677,6 +650,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
: R.string.layout_middle_side_prompt_attach_only); : R.string.layout_middle_side_prompt_attach_only);
SbtSettings.ensureReadable(requireContext()); SbtSettings.ensureReadable(requireContext());
}); });
}
side.setOnCheckedChangeListener((group, checkedId) -> { side.setOnCheckedChangeListener((group, checkedId) -> {
prefs.edit().putString(middleSideKey, checkedId == middleSideRightId ? "right" : "left").apply(); prefs.edit().putString(middleSideKey, checkedId == middleSideRightId ? "right" : "left").apply();
SbtSettings.ensureReadable(requireContext()); SbtSettings.ensureReadable(requireContext());
@@ -709,14 +683,14 @@ abstract class LockedSceneLayoutFragment extends Fragment {
if (reset != null) { if (reset != null) {
reset.setOnClickListener(v -> { reset.setOnClickListener(v -> {
input.setText(String.valueOf(defaultValue)); input.setText(String.valueOf(defaultValue));
persistIntPref(prefs, key, defaultValue); ViewTreeSupport.persistIntPreference(requireContext(), prefs, key, defaultValue);
}); });
} }
input.setOnFocusChangeListener((v, hasFocus) -> { input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) { if (!hasFocus) {
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, defaultValue), min, max); int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, defaultValue), min, max);
input.setText(String.valueOf(next)); input.setText(String.valueOf(next));
persistIntPref(prefs, key, next); ViewTreeSupport.persistIntPreference(requireContext(), prefs, key, next);
} }
}); });
} }
@@ -736,7 +710,7 @@ abstract class LockedSceneLayoutFragment extends Fragment {
button.setOnClickListener(v -> { button.setOnClickListener(v -> {
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, 0) + delta, min, max); int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, 0) + delta, min, max);
input.setText(String.valueOf(next)); input.setText(String.valueOf(next));
persistIntPref(prefs, key, next); ViewTreeSupport.persistIntPreference(requireContext(), prefs, key, next);
}); });
} }
@@ -822,79 +796,22 @@ abstract class LockedSceneLayoutFragment extends Fragment {
int max, int max,
boolean showDefaultButton boolean showDefaultButton
) { ) {
LinearLayout outer = vertical(context); return ViewTreeSupport.intPreferenceStepper(
outer.addView(body(context, label)); context,
LinearLayout row = new LinearLayout(context); prefs,
row.setOrientation(LinearLayout.HORIZONTAL); label,
row.setGravity(Gravity.CENTER_VERTICAL); key,
MaterialButton minus = ViewTreeSupport.outlinedStepperButton(context, "-"); def,
MaterialButton plus = ViewTreeSupport.outlinedStepperButton(context, "+"); min,
MaterialButton reset = showDefaultButton max,
? ViewTreeSupport.outlinedStepperButton(context, "D") true,
: null; 4,
EditText input = ViewTreeSupport.numericInput(context, true, 4); 6,
input.setText(String.valueOf(ViewTreeSupport.clamp(prefs.getInt(key, def), min, max))); 0,
row.addView(minus, ViewTreeSupport.stepperButtonParams(context)); 0,
row.addView(input, ViewTreeSupport.stepperInputParams(context)); showDefaultButton,
row.addView(plus, ViewTreeSupport.stepperButtonParams(context)); false,
if (reset != null) { null);
LinearLayout.LayoutParams resetParams = ViewTreeSupport.stepperButtonParams(context);
resetParams.leftMargin = ViewTreeSupport.dp(context, 8);
row.addView(reset, resetParams);
}
outer.addView(row);
View.OnClickListener listener = view -> {
int delta = view == minus ? -1 : 1;
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, def) + delta, min, max);
input.setText(String.valueOf(next));
persistIntPref(prefs, key, next);
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
if (reset != null) {
reset.setOnClickListener(v -> {
int next = ViewTreeSupport.clamp(def, min, max);
input.setText(String.valueOf(next));
persistIntPref(prefs, key, next);
});
}
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = ViewTreeSupport.clamp(ViewTreeSupport.parseInt(input, def), min, max);
input.setText(String.valueOf(next));
persistIntPref(prefs, key, next);
}
});
return outer;
}
private void persistIntPref(SharedPreferences prefs, String key, int value) {
prefs.edit().putInt(key, value).apply();
SbtSettings.ensureReadable(requireContext());
}
private int iconContainerCount(
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
boolean legacyEnabledDefault
) {
int fallback = prefs.getBoolean(legacyEnabledKey, legacyEnabledDefault) ? 1 : 0;
return SbtSettings.clampIconContainerCount(prefs.getInt(countKey, fallback));
}
private void persistIconContainerCount(
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
int count
) {
int clamped = SbtSettings.clampIconContainerCount(count);
prefs.edit()
.putInt(countKey, clamped)
.putBoolean(legacyEnabledKey, clamped > 0)
.apply();
SbtSettings.ensureReadable(requireContext());
} }
private String sceneKey(String suffix) { private String sceneKey(String suffix) {
@@ -922,23 +839,10 @@ abstract class LockedSceneLayoutFragment extends Fragment {
return content instanceof LinearLayout layout ? layout : null; return content instanceof LinearLayout layout ? layout : null;
} }
private View card(Context context, int titleId, View content) { private View outlinedCard(Context context, int titleId, View content) {
return ViewTreeSupport.outlinedCard(context, sectionTitle(context, titleId), content); return ViewTreeSupport.outlinedCard(
} context,
ViewTreeSupport.sectionTitleText(context, titleId, false),
private LinearLayout vertical(Context context) { content);
return ViewTreeSupport.verticalLayout(context);
}
private TextView title(Context context, int text) {
return ViewTreeSupport.titleText(context, text);
}
private TextView sectionTitle(Context context, int text) {
return ViewTreeSupport.sectionTitleText(context, text, false);
}
private TextView body(Context context, int text) {
return ViewTreeSupport.bodyText(context, text, 6);
} }
} }
@@ -14,8 +14,9 @@ import android.widget.TextView;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.card.MaterialCardView; import com.google.android.material.card.MaterialCardView;
import se.ajpanton.statusbartweak.R; import java.util.function.IntConsumer;
import se.ajpanton.statusbartweak.R;
import se.ajpanton.statusbartweak.shell.settings.SbtSettings; import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
final class ViewTreeSupport { final class ViewTreeSupport {
@@ -149,6 +150,160 @@ final class ViewTreeSupport {
return input; return input;
} }
static int iconContainerCount(
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
int defaultCount,
boolean legacyEnabledDefault
) {
int fallback = prefs.getBoolean(legacyEnabledKey, legacyEnabledDefault) ? defaultCount : 0;
return SbtSettings.clampIconContainerCount(prefs.getInt(countKey, fallback));
}
static void persistIconContainerCount(
Context context,
SharedPreferences prefs,
String countKey,
String legacyEnabledKey,
int count
) {
int clamped = SbtSettings.clampIconContainerCount(count);
prefs.edit()
.putInt(countKey, clamped)
.putBoolean(legacyEnabledKey, clamped > 0)
.apply();
SbtSettings.ensureReadable(context);
}
static View iconContainerCountControl(
Context context,
int current,
IntConsumer countPersister,
Runnable onChanged
) {
LinearLayout outer = verticalLayout(context);
outer.addView(bodyText(context, R.string.layout_icon_container_count, 0));
LinearLayout row = new LinearLayout(context);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setGravity(android.view.Gravity.CENTER_VERTICAL);
MaterialButton minus = outlinedStepperButton(context, "-");
MaterialButton plus = outlinedStepperButton(context, "+");
EditText input = numericInput(context, false, 1);
input.setText(String.valueOf(current));
row.addView(minus, stepperButtonParams(context));
row.addView(input, stepperInputParams(context));
row.addView(plus, stepperButtonParams(context));
outer.addView(row);
View.OnClickListener listener = view -> {
int next = SbtSettings.clampIconContainerCount(
parseInt(input, current) + (view == minus ? -1 : 1));
countPersister.accept(next);
onChanged.run();
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = SbtSettings.clampIconContainerCount(parseInt(input, current));
countPersister.accept(next);
onChanged.run();
}
});
return outer;
}
static View intPreferenceStepper(
Context context,
SharedPreferences prefs,
int labelRes,
String key,
int defaultValue,
int min,
int max,
boolean signed,
int inputMaxLength,
int labelBottomPaddingDp,
int rowTopPaddingDp,
int rowBottomPaddingDp,
boolean showDefaultButton,
boolean useCurrentAsParseFallback,
View trailingView
) {
LinearLayout outer = verticalLayout(context);
outer.addView(bodyText(context, labelRes, labelBottomPaddingDp));
LinearLayout row = new LinearLayout(context);
row.setOrientation(LinearLayout.HORIZONTAL);
row.setGravity(android.view.Gravity.CENTER_VERTICAL);
row.setPadding(0, dp(context, rowTopPaddingDp), 0, dp(context, rowBottomPaddingDp));
MaterialButton minus = outlinedStepperButton(context, "-");
MaterialButton plus = outlinedStepperButton(context, "+");
MaterialButton reset = showDefaultButton ? outlinedStepperButton(context, "D") : null;
EditText input = numericInput(context, signed, inputMaxLength);
int current = clamp(prefs.getInt(key, defaultValue), min, max);
int parseFallback = useCurrentAsParseFallback ? current : defaultValue;
input.setText(String.valueOf(current));
row.addView(minus, stepperButtonParams(context));
row.addView(input, stepperInputParams(context));
row.addView(plus, stepperButtonParams(context));
if (reset != null) {
LinearLayout.LayoutParams resetParams = stepperButtonParams(context);
resetParams.leftMargin = dp(context, 8);
row.addView(reset, resetParams);
}
if (trailingView != null) {
LinearLayout.LayoutParams trailingParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
trailingParams.leftMargin = dp(context, 8);
row.addView(trailingView, trailingParams);
}
outer.addView(row);
View.OnClickListener listener = view -> {
int delta = view == minus ? -1 : 1;
int next = clamp(parseInt(input, parseFallback) + delta, min, max);
persistIntPreference(context, prefs, key, input, next);
};
minus.setOnClickListener(listener);
plus.setOnClickListener(listener);
if (reset != null) {
reset.setOnClickListener(v -> persistIntPreference(
context,
prefs,
key,
input,
clamp(defaultValue, min, max)));
}
input.setOnFocusChangeListener((v, hasFocus) -> {
if (!hasFocus) {
int next = clamp(parseInt(input, parseFallback), min, max);
persistIntPreference(context, prefs, key, input, next);
}
});
return outer;
}
static void persistIntPreference(
Context context,
SharedPreferences prefs,
String key,
EditText input,
int value
) {
input.setText(String.valueOf(value));
persistIntPreference(context, prefs, key, value);
}
static void persistIntPreference(Context context, SharedPreferences prefs, String key, int value) {
prefs.edit().putInt(key, value).apply();
SbtSettings.ensureReadable(context);
}
static LinearLayout verticalLayout(Context context) { static LinearLayout verticalLayout(Context context) {
LinearLayout layout = new LinearLayout(context); LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL); layout.setOrientation(LinearLayout.VERTICAL);
@@ -317,18 +317,10 @@
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
<CheckBox
android:id="@+id/chip_middle_auto_nearest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/layout_middle_auto_nearest" />
<TextView <TextView
android:id="@+id/chip_middle_side_prompt" android:id="@+id/chip_middle_side_prompt"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/layout_middle_side_prompt" android:text="@string/layout_middle_side_prompt"
android:textAppearance="?attr/textAppearanceBody2" /> android:textAppearance="?attr/textAppearanceBody2" />
@@ -546,18 +538,10 @@
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
<CheckBox
android:id="@+id/notif_middle_auto_nearest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/layout_middle_auto_nearest" />
<TextView <TextView
android:id="@+id/notif_middle_side_prompt" android:id="@+id/notif_middle_side_prompt"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/layout_middle_side_prompt" android:text="@string/layout_middle_side_prompt"
android:textAppearance="?attr/textAppearanceBody2" /> android:textAppearance="?attr/textAppearanceBody2" />
@@ -775,18 +759,10 @@
android:orientation="vertical" android:orientation="vertical"
android:visibility="gone"> android:visibility="gone">
<CheckBox
android:id="@+id/status_middle_auto_nearest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/layout_middle_auto_nearest" />
<TextView <TextView
android:id="@+id/status_middle_side_prompt" android:id="@+id/status_middle_side_prompt"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/layout_middle_side_prompt" android:text="@string/layout_middle_side_prompt"
android:textAppearance="?attr/textAppearanceBody2" /> android:textAppearance="?attr/textAppearanceBody2" />
-2
View File
@@ -209,8 +209,6 @@
<string name="clock_position_right">Right</string> <string name="clock_position_right">Right</string>
<string name="clock_position_middle">Middle</string> <string name="clock_position_middle">Middle</string>
<string name="clock_vertical_offset_label">Vertical position</string> <string name="clock_vertical_offset_label">Vertical position</string>
<string name="clock_middle_auto_nearest">If Middle overlaps the cutout, move it to the nearest side.</string>
<string name="clock_middle_cutout_prompt">Else, or if the overlap is centred, move clock to:</string>
<string name="clock_middle_side_left">Left side</string> <string name="clock_middle_side_left">Left side</string>
<string name="clock_middle_side_right">Right side</string> <string name="clock_middle_side_right">Right side</string>
<string name="clock_custom_format_title">Custom format</string> <string name="clock_custom_format_title">Custom format</string>
@@ -1,17 +0,0 @@
package se.ajpanton.statusbartweak;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
@@ -21,9 +21,7 @@ public final class UnlockedLayoutBandTest {
null, null,
placements(6, 39, 39), placements(6, 39, 39),
LayoutPosition.LEFT, LayoutPosition.LEFT,
false, AnchorSide.LEFT);
AnchorSide.LEFT,
true);
band.applyPackedIconState(0, 0, true, 14); band.applyPackedIconState(0, 0, true, 14);
band.place(388); band.place(388);
@@ -54,9 +52,7 @@ public final class UnlockedLayoutBandTest {
null, null,
placements, placements,
LayoutPosition.LEFT, LayoutPosition.LEFT,
false, AnchorSide.LEFT);
AnchorSide.LEFT,
true);
band.applyPackedIconState(2, 3, false, 117); band.applyPackedIconState(2, 3, false, 117);
@@ -86,9 +82,7 @@ public final class UnlockedLayoutBandTest {
null, null,
placements, placements,
LayoutPosition.LEFT, LayoutPosition.LEFT,
false, AnchorSide.LEFT);
AnchorSide.LEFT,
false);
band.prepareForSide(AnchorSide.RIGHT, "normal"); band.prepareForSide(AnchorSide.RIGHT, "normal");
band.applyPackedContinuousWidth(211, AnchorSide.RIGHT); band.applyPackedContinuousWidth(211, AnchorSide.RIGHT);