Complete shared AOD layout engine
This commit is contained in:
+18
-3
@@ -17,6 +17,7 @@ import java.util.WeakHashMap;
|
|||||||
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
|
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
|
||||||
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.mode.SceneKey;
|
||||||
import se.ajpanton.statusbartweak.runtime.settings.RuntimeSettingsCache;
|
import se.ajpanton.statusbartweak.runtime.settings.RuntimeSettingsCache;
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtDefaults;
|
import se.ajpanton.statusbartweak.shell.settings.SbtDefaults;
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||||
@@ -46,27 +47,33 @@ final class StockUnlockedNotificationIconsController {
|
|||||||
Class<?> containerClass = ReflectionSupport.requireClass(CONTAINER_CLASS_NAME, classLoader);
|
Class<?> containerClass = ReflectionSupport.requireClass(CONTAINER_CLASS_NAME, classLoader);
|
||||||
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onAttachedToWindow", chain -> {
|
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onAttachedToWindow", chain -> {
|
||||||
Object result = chain.proceed();
|
Object result = chain.proceed();
|
||||||
if (chain.getThisObject() instanceof View view && shouldManageContainer(view)) {
|
if (chain.getThisObject() instanceof View view) {
|
||||||
|
if (shouldManageContainer(view)) {
|
||||||
trackContainer(view);
|
trackContainer(view);
|
||||||
view.post(() -> refreshContainer(view));
|
view.post(() -> refreshContainer(view));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "calculateIconXTranslations", chain -> {
|
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "calculateIconXTranslations", chain -> {
|
||||||
if (chain.getThisObject() instanceof View view && shouldManageContainer(view)) {
|
if (chain.getThisObject() instanceof View view) {
|
||||||
|
if (shouldManageContainer(view)) {
|
||||||
trackContainer(view);
|
trackContainer(view);
|
||||||
applyLimitIfNeeded(view);
|
applyLimitIfNeeded(view);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return chain.proceed();
|
return chain.proceed();
|
||||||
});
|
});
|
||||||
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onLayout", chain -> {
|
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "onLayout", chain -> {
|
||||||
Object result = chain.proceed();
|
Object result = chain.proceed();
|
||||||
if (chain.getThisObject() instanceof View view && shouldManageContainer(view)) {
|
if (chain.getThisObject() instanceof View view) {
|
||||||
|
if (shouldManageContainer(view)) {
|
||||||
trackContainer(view);
|
trackContainer(view);
|
||||||
if (isFeatureEnabled(view.getContext())) {
|
if (isFeatureEnabled(view.getContext())) {
|
||||||
enforceParentWidth(view);
|
enforceParentWidth(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "shouldForceOverflow", chain -> {
|
XposedHookSupport.hookAllMethods(runtimeContext.getFramework(), containerClass, "shouldForceOverflow", chain -> {
|
||||||
@@ -236,6 +243,9 @@ final class StockUnlockedNotificationIconsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldManageContainer(View view) {
|
private boolean shouldManageContainer(View view) {
|
||||||
|
if (!isUnlockedScene()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (isKeyguardContainer(view)) {
|
if (isKeyguardContainer(view)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -260,6 +270,11 @@ final class StockUnlockedNotificationIconsController {
|
|||||||
return inUnlockedStatusBarIconArea;
|
return inUnlockedStatusBarIconArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isUnlockedScene() {
|
||||||
|
SceneKey scene = runtimeContext.getModeStateRepository().getActiveScene();
|
||||||
|
return scene != null && scene.isUnlocked();
|
||||||
|
}
|
||||||
|
|
||||||
private String resolveIdName(View view) {
|
private String resolveIdName(View view) {
|
||||||
if (view == null || view.getId() == View.NO_ID) {
|
if (view == null || view.getId() == View.NO_ID) {
|
||||||
return "";
|
return "";
|
||||||
|
|||||||
+2462
-158
File diff suppressed because it is too large
Load Diff
+36
-9
@@ -265,15 +265,17 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
neededForItem = Math.max(neededForItem, constraint.required - assumedAbsorberCapacity);
|
neededForItem = Math.max(neededForItem, constraint.required - assumedAbsorberCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<LayoutItem> groupItems = item.isIconItem()
|
||||||
|
? iconGroups.get(item.iconGroup)
|
||||||
|
: null;
|
||||||
double amount = Math.min(Math.max(0, neededForItem), contextualShrinkCapacity(item, item));
|
double amount = Math.min(Math.max(0, neededForItem), contextualShrinkCapacity(item, item));
|
||||||
double directActual = item.isIconItem()
|
double directActual = item.isIconItem()
|
||||||
? truncateIconItemWithoutDot(item, amount)
|
? truncateIconItemWithoutDot(item, amount, groupItems != null && groupItems.size() > 1)
|
||||||
: item.truncateAtLeast(amount);
|
: item.truncateAtLeast(amount);
|
||||||
if (directActual != 0) {
|
if (directActual != 0) {
|
||||||
adjustConstraintsForItemWidthDelta(constraints, item, directActual);
|
adjustConstraintsForItemWidthDelta(constraints, item, directActual);
|
||||||
}
|
}
|
||||||
if (item.isIconItem()) {
|
if (item.isIconItem()) {
|
||||||
ArrayList<LayoutItem> groupItems = iconGroups.get(item.iconGroup);
|
|
||||||
ArrayList<Integer> remaining = remainingIconWidths.get(item.iconGroup);
|
ArrayList<Integer> remaining = remainingIconWidths.get(item.iconGroup);
|
||||||
int remainingStart = remainingIconStarts.getOrDefault(item.iconGroup, 0);
|
int remainingStart = remainingIconStarts.getOrDefault(item.iconGroup, 0);
|
||||||
ArrayList<Integer> remainingAfterItem = allocateCurrentIconItem(
|
ArrayList<Integer> remainingAfterItem = allocateCurrentIconItem(
|
||||||
@@ -336,7 +338,14 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
return item.canShrinkBy();
|
return item.canShrinkBy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double truncateIconItemWithoutDot(LayoutItem item, double amount) {
|
private static double truncateIconItemWithoutDot(
|
||||||
|
LayoutItem item,
|
||||||
|
double amount,
|
||||||
|
boolean allowZeroWithoutDot
|
||||||
|
) {
|
||||||
|
if (!allowZeroWithoutDot) {
|
||||||
|
return item.truncateAtLeast(amount);
|
||||||
|
}
|
||||||
boolean oldAllowZero = item.allowZero;
|
boolean oldAllowZero = item.allowZero;
|
||||||
boolean oldAllowDot = item.allowDot;
|
boolean oldAllowDot = item.allowDot;
|
||||||
item.allowZero = true;
|
item.allowZero = true;
|
||||||
@@ -403,8 +412,9 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
}
|
}
|
||||||
ArrayList<Integer> remaining = new ArrayList<>(groupItems.get(0).iconWidths());
|
ArrayList<Integer> remaining = new ArrayList<>(groupItems.get(0).iconWidths());
|
||||||
int start = 0;
|
int start = 0;
|
||||||
|
boolean allowZeroWithoutDot = groupItems.size() > 1;
|
||||||
for (LayoutItem item : groupItems) {
|
for (LayoutItem item : groupItems) {
|
||||||
setIconItemPool(item, remaining, start);
|
setIconItemPool(item, remaining, start, allowZeroWithoutDot);
|
||||||
int used = item.visibleIcons;
|
int used = item.visibleIcons;
|
||||||
remaining = sliceFrom(remaining, used);
|
remaining = sliceFrom(remaining, used);
|
||||||
start += used;
|
start += used;
|
||||||
@@ -420,12 +430,13 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
ArrayList<FinalConstraint> constraints
|
ArrayList<FinalConstraint> constraints
|
||||||
) {
|
) {
|
||||||
HashMap<LayoutItem, Double> oldWidths = widthsByItem(groupItems);
|
HashMap<LayoutItem, Double> oldWidths = widthsByItem(groupItems);
|
||||||
setIconItemPool(item, remainingWidths, remainingStart);
|
boolean allowZeroWithoutDot = groupItems != null && groupItems.size() > 1;
|
||||||
|
setIconItemPool(item, remainingWidths, remainingStart, allowZeroWithoutDot);
|
||||||
ArrayList<Integer> remainingAfterItem = sliceFrom(remainingWidths, item.visibleIcons);
|
ArrayList<Integer> remainingAfterItem = sliceFrom(remainingWidths, item.visibleIcons);
|
||||||
int remainingAfterStart = remainingStart + item.visibleIcons;
|
int remainingAfterStart = remainingStart + item.visibleIcons;
|
||||||
int itemIndex = groupItems.indexOf(item);
|
int itemIndex = groupItems.indexOf(item);
|
||||||
for (int i = itemIndex + 1; i < groupItems.size(); i++) {
|
for (int i = itemIndex + 1; i < groupItems.size(); i++) {
|
||||||
setIconItemPool(groupItems.get(i), remainingAfterItem, remainingAfterStart);
|
setIconItemPool(groupItems.get(i), remainingAfterItem, remainingAfterStart, true);
|
||||||
}
|
}
|
||||||
adjustGroupConstraintDeltas(groupItems, oldWidths, constraints);
|
adjustGroupConstraintDeltas(groupItems, oldWidths, constraints);
|
||||||
return remainingAfterItem;
|
return remainingAfterItem;
|
||||||
@@ -451,7 +462,17 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
adjustGroupConstraintDeltas(groupItems, oldWidths, constraints);
|
adjustGroupConstraintDeltas(groupItems, oldWidths, constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setIconItemPool(LayoutItem item, ArrayList<Integer> widths, int startIndex) {
|
private static void setIconItemPool(
|
||||||
|
LayoutItem item,
|
||||||
|
ArrayList<Integer> widths,
|
||||||
|
int startIndex,
|
||||||
|
boolean allowZeroWithoutDot
|
||||||
|
) {
|
||||||
|
if (!allowZeroWithoutDot) {
|
||||||
|
item.widthLimit = Math.min(item.currentWidthLimit(), item.width());
|
||||||
|
item.setPoolIcons(widths, startIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
boolean oldAllowZero = item.allowZero;
|
boolean oldAllowZero = item.allowZero;
|
||||||
boolean oldAllowDot = item.allowDot;
|
boolean oldAllowDot = item.allowDot;
|
||||||
item.allowZero = true;
|
item.allowZero = true;
|
||||||
@@ -494,6 +515,12 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
}
|
}
|
||||||
LayoutItem item = groupItems.get(lastIcons);
|
LayoutItem item = groupItems.get(lastIcons);
|
||||||
if (item.visibleIconWidths.isEmpty()) {
|
if (item.visibleIconWidths.isEmpty()) {
|
||||||
|
if (item.allowDot && item.poolRemaining > 0) {
|
||||||
|
item.dot = true;
|
||||||
|
item.visibleIcons = 0;
|
||||||
|
item.setPrimaryWidth(dotWidthForFinalPlacement(groupItems, item));
|
||||||
|
item.widthLimit = item.width();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
item.visibleIconWidths.remove(item.visibleIconWidths.size() - 1);
|
item.visibleIconWidths.remove(item.visibleIconWidths.size() - 1);
|
||||||
@@ -515,7 +542,7 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allLaterZero) {
|
if (allLaterZero && item.noCollisionsOnSide(false)) {
|
||||||
return Math.min(dotWidth, item.dotWidth - item.dotWidth / 3.0);
|
return Math.min(dotWidth, item.dotWidth - item.dotWidth / 3.0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -526,7 +553,7 @@ public final class PackedStatusBarLayoutSolver {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allEarlierZero) {
|
if (allEarlierZero && item.noCollisionsOnSide(true)) {
|
||||||
return Math.min(dotWidth, item.dotWidth - item.dotWidth / 3.0);
|
return Math.min(dotWidth, item.dotWidth - item.dotWidth / 3.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+54
-18
@@ -13,12 +13,12 @@ import java.util.Objects;
|
|||||||
* runtime API.
|
* runtime API.
|
||||||
*/
|
*/
|
||||||
public final class ModeStateRepository {
|
public final class ModeStateRepository {
|
||||||
|
|
||||||
private SceneKey activeScene = SceneKey.unlocked();
|
private SceneKey activeScene = SceneKey.unlocked();
|
||||||
private boolean systemUiStatusBarStateKnown;
|
private boolean systemUiStatusBarStateKnown;
|
||||||
private int systemUiStatusBarState;
|
private int systemUiStatusBarState;
|
||||||
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<>();
|
||||||
|
|
||||||
public synchronized SceneKey getActiveScene() {
|
public synchronized SceneKey getActiveScene() {
|
||||||
return activeScene;
|
return activeScene;
|
||||||
@@ -56,39 +56,71 @@ public final class ModeStateRepository {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setUnlocked() {
|
public void setUnlocked() {
|
||||||
activeScene = SceneKey.unlocked();
|
setActiveScene(SceneKey.unlocked());
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setLockscreen(NotificationDisplayStyle style) {
|
public void setLockscreen(NotificationDisplayStyle style) {
|
||||||
activeScene = SceneKey.lockscreen(requireDisplayStyle(style));
|
setActiveScene(SceneKey.lockscreen(requireDisplayStyle(style)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setAod(NotificationDisplayStyle style) {
|
public void setAod(NotificationDisplayStyle style) {
|
||||||
activeScene = SceneKey.aod(requireDisplayStyle(style));
|
setActiveScene(SceneKey.aod(requireDisplayStyle(style)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setScene(SceneKey sceneKey) {
|
public void setScene(SceneKey sceneKey) {
|
||||||
activeScene = Objects.requireNonNull(sceneKey, "sceneKey");
|
setActiveScene(Objects.requireNonNull(sceneKey, "sceneKey"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setSystemUiStatusBarState(
|
public void setSystemUiStatusBarState(
|
||||||
int state,
|
int state,
|
||||||
boolean dozing,
|
boolean dozing,
|
||||||
NotificationDisplayStyle notificationDisplayStyle
|
NotificationDisplayStyle notificationDisplayStyle
|
||||||
) {
|
) {
|
||||||
systemUiStatusBarStateKnown = true;
|
|
||||||
systemUiStatusBarState = state;
|
|
||||||
NotificationDisplayStyle style = notificationDisplayStyle;
|
NotificationDisplayStyle style = notificationDisplayStyle;
|
||||||
if (style == null || style == NotificationDisplayStyle.NONE) {
|
if (style == null || style == NotificationDisplayStyle.NONE) {
|
||||||
style = NotificationDisplayStyle.UNKNOWN;
|
style = NotificationDisplayStyle.UNKNOWN;
|
||||||
}
|
}
|
||||||
if (dozing) {
|
SceneKey scene = dozing
|
||||||
activeScene = SceneKey.aod(style);
|
? SceneKey.aod(style)
|
||||||
} else if (state == 0) {
|
: state == 0 ? SceneKey.unlocked() : SceneKey.lockscreen(style);
|
||||||
activeScene = SceneKey.unlocked();
|
synchronized (this) {
|
||||||
} else {
|
systemUiStatusBarStateKnown = true;
|
||||||
activeScene = SceneKey.lockscreen(style);
|
systemUiStatusBarState = state;
|
||||||
|
}
|
||||||
|
setActiveScene(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void addSceneListener(SceneListener listener) {
|
||||||
|
if (listener != null && !sceneListeners.contains(listener)) {
|
||||||
|
sceneListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setActiveScene(SceneKey scene) {
|
||||||
|
SceneKey previous;
|
||||||
|
List<SceneListener> listeners;
|
||||||
|
synchronized (this) {
|
||||||
|
previous = activeScene;
|
||||||
|
if (previous.equals(scene)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activeScene = scene;
|
||||||
|
listeners = new ArrayList<>(sceneListeners);
|
||||||
|
}
|
||||||
|
notifySceneChanged(previous, scene, listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifySceneChanged(
|
||||||
|
SceneKey previous,
|
||||||
|
SceneKey current,
|
||||||
|
List<SceneListener> listeners
|
||||||
|
) {
|
||||||
|
if (listeners == null || listeners.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (SceneListener listener : listeners) {
|
||||||
|
listener.onSceneChanged(previous, current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,4 +134,8 @@ public final class ModeStateRepository {
|
|||||||
public interface LayoutEnabledListener {
|
public interface LayoutEnabledListener {
|
||||||
void onLayoutEnabledChanged(boolean enabled);
|
void onLayoutEnabledChanged(boolean enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface SceneListener {
|
||||||
|
void onSceneChanged(SceneKey previous, SceneKey current);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+151
@@ -0,0 +1,151 @@
|
|||||||
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
|
||||||
|
|
||||||
|
final class AodLiveStatusbarSource {
|
||||||
|
private AodLiveStatusbarSource() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bounds movingBoundsForRoot(View root) {
|
||||||
|
View source = sourceForRoot(root, true);
|
||||||
|
return usableBounds(root, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bounds movingIconContentBoundsForRoot(View root) {
|
||||||
|
View source = sourceForRoot(root, true);
|
||||||
|
Bounds sourceBounds = usableBounds(root, source);
|
||||||
|
if (!(source instanceof ViewGroup group)) {
|
||||||
|
return sourceBounds;
|
||||||
|
}
|
||||||
|
Bounds union = null;
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (!isIconContentCandidate(child)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds childBounds = usableBounds(root, child);
|
||||||
|
if (childBounds == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
union = union == null ? childBounds : union(union, childBounds);
|
||||||
|
}
|
||||||
|
return union != null ? union : sourceBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bounds boundsForRoot(View root) {
|
||||||
|
View source = sourceForRoot(root, false);
|
||||||
|
return usableBounds(root, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static View sourceForRoot(View root, boolean movingOnly) {
|
||||||
|
if (!(root instanceof ViewGroup rootGroup)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
View best = null;
|
||||||
|
int bestPriority = Integer.MAX_VALUE;
|
||||||
|
ArrayDeque<View> queue = new ArrayDeque<>();
|
||||||
|
queue.add(rootGroup);
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
View view = queue.removeFirst();
|
||||||
|
int priority = sourcePriority(view, movingOnly);
|
||||||
|
if (priority < bestPriority && usableBounds(root, view) != null) {
|
||||||
|
best = view;
|
||||||
|
bestPriority = priority;
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (child != null) {
|
||||||
|
queue.addLast(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int sourcePriority(View view, boolean movingOnly) {
|
||||||
|
String idName = resolveIdName(view);
|
||||||
|
if ("common_statusbar_battery_container_internal".equals(idName)
|
||||||
|
&& view instanceof ViewGroup group
|
||||||
|
&& group.getChildCount() > 0
|
||||||
|
&& shortEnough(view)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!movingOnly
|
||||||
|
&& "system_icons".equals(idName)
|
||||||
|
&& view instanceof ViewGroup group
|
||||||
|
&& group.getChildCount() > 0
|
||||||
|
&& hasAncestorId(view, "system_icons_container")
|
||||||
|
&& hasAncestorId(view, "status_icon_area")
|
||||||
|
&& shortEnough(view)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean shortEnough(View view) {
|
||||||
|
int height = view.getHeight() > 0 ? view.getHeight() : view.getMeasuredHeight();
|
||||||
|
return height > 0 && height <= 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isIconContentCandidate(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String className = view.getClass().getName();
|
||||||
|
if (className.contains("BatteryMeterView")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return className.contains("ImageView") || className.contains("StatusBarIcon");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds union(Bounds first, Bounds second) {
|
||||||
|
int left = Math.min(first.left, second.left);
|
||||||
|
int top = Math.min(first.top, second.top);
|
||||||
|
int right = Math.max(first.left + first.width, second.left + second.width);
|
||||||
|
int bottom = Math.max(first.top + first.height, second.top + second.height);
|
||||||
|
return new Bounds(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds usableBounds(View root, View view) {
|
||||||
|
Bounds bounds = ViewGeometry.boundsRelativeTo(root, view);
|
||||||
|
if (root == null || bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int right = bounds.left + bounds.width;
|
||||||
|
int bottom = bounds.top + bounds.height;
|
||||||
|
if (bounds.left < 0 || bounds.top < 0 || right > root.getWidth() || bottom > root.getHeight()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasAncestorId(View view, String idName) {
|
||||||
|
Object parent = view != null ? view.getParent() : null;
|
||||||
|
while (parent instanceof View parentView) {
|
||||||
|
if (idName.equals(resolveIdName(parentView))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
parent = parentView.getParent();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String resolveIdName(View view) {
|
||||||
|
if (view == null || view.getId() == View.NO_ID) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return view.getResources().getResourceEntryName(view.getId());
|
||||||
|
} catch (Resources.NotFoundException ignored) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+249
@@ -0,0 +1,249 @@
|
|||||||
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
|
||||||
|
|
||||||
|
public final class AodStatusbarSourceStore {
|
||||||
|
private static final WeakHashMap<View, StatusSourceRole> STATUS_SOURCES = new WeakHashMap<>();
|
||||||
|
|
||||||
|
public enum StatusSourceRole {
|
||||||
|
SYSTEM_ICONS,
|
||||||
|
STATUS_ICONS,
|
||||||
|
BATTERY,
|
||||||
|
UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
private AodStatusbarSourceStore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putStatusContainer(View view) {
|
||||||
|
putStatusSource(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putStatusSource(View view) {
|
||||||
|
if (view != null) {
|
||||||
|
STATUS_SOURCES.put(view, StatusSourceRole.UNKNOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putStatusSource(View view, StatusSourceRole role) {
|
||||||
|
if (view != null) {
|
||||||
|
STATUS_SOURCES.put(view, role != null ? role : StatusSourceRole.UNKNOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void replaceStatusSources(List<View> views) {
|
||||||
|
STATUS_SOURCES.clear();
|
||||||
|
if (views == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (View view : views) {
|
||||||
|
putStatusSource(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void replaceStatusSources(
|
||||||
|
View systemIcons,
|
||||||
|
View statusIcons,
|
||||||
|
View battery
|
||||||
|
) {
|
||||||
|
STATUS_SOURCES.clear();
|
||||||
|
putStatusSource(systemIcons, StatusSourceRole.SYSTEM_ICONS);
|
||||||
|
putStatusSource(statusIcons, StatusSourceRole.STATUS_ICONS);
|
||||||
|
putStatusSource(battery, StatusSourceRole.BATTERY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void replaceStatusContainer(View view) {
|
||||||
|
STATUS_SOURCES.clear();
|
||||||
|
putStatusSource(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
STATUS_SOURCES.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bounds statusBoundsForRoot(View root, View excludedContainer) {
|
||||||
|
if (root == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Bounds union = null;
|
||||||
|
for (View source : STATUS_SOURCES.keySet()) {
|
||||||
|
if (!isUsableSource(root, source, excludedContainer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isStatusAnchorSource(STATUS_SOURCES.get(source))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds bounds = boundsForRoot(root, source);
|
||||||
|
if (!isUsableRightAnchor(root, bounds)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
union = union == null ? bounds : union(union, bounds);
|
||||||
|
}
|
||||||
|
return union;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ArrayList<Bounds> statusBoundsListForRoot(View root, View excludedContainer) {
|
||||||
|
ArrayList<Bounds> result = new ArrayList<>();
|
||||||
|
if (root == null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (View source : STATUS_SOURCES.keySet()) {
|
||||||
|
if (!isUsableSource(root, source, excludedContainer)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isStatusAnchorSource(STATUS_SOURCES.get(source))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds bounds = boundsForRoot(root, source);
|
||||||
|
if (isUsableRightAnchor(root, bounds)) {
|
||||||
|
result.add(bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isStatusAnchorSource(StatusSourceRole role) {
|
||||||
|
return role != StatusSourceRole.SYSTEM_ICONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds union(Bounds first, Bounds second) {
|
||||||
|
if (first == null) {
|
||||||
|
return second;
|
||||||
|
}
|
||||||
|
if (second == null) {
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
int left = Math.min(first.left, second.left);
|
||||||
|
int top = Math.min(first.top, second.top);
|
||||||
|
int right = Math.max(right(first), right(second));
|
||||||
|
int bottom = Math.max(first.top + first.height, second.top + second.height);
|
||||||
|
return new Bounds(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUsableSource(View root, View source, View excludedContainer) {
|
||||||
|
return source != null
|
||||||
|
&& source != excludedContainer
|
||||||
|
&& !isRelated(source, excludedContainer)
|
||||||
|
&& !isNotificationContainer(source)
|
||||||
|
&& !isOwnedRuntimeView(source)
|
||||||
|
&& source.isAttachedToWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds boundsForRoot(View root, View view) {
|
||||||
|
Bounds localBounds = ViewGeometry.boundsRelativeTo(root, view);
|
||||||
|
if (localBounds != null) {
|
||||||
|
return clampToRoot(root, localBounds);
|
||||||
|
}
|
||||||
|
return screenBoundsRelativeTo(root, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds screenBoundsRelativeTo(View root, View view) {
|
||||||
|
if (root == null || view == null || root.getWidth() <= 0 || root.getHeight() <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
||||||
|
int height = view.getHeight() > 0 ? view.getHeight() : view.getMeasuredHeight();
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int[] rootLocation = new int[2];
|
||||||
|
int[] viewLocation = new int[2];
|
||||||
|
root.getLocationOnScreen(rootLocation);
|
||||||
|
view.getLocationOnScreen(viewLocation);
|
||||||
|
int left = viewLocation[0] - rootLocation[0];
|
||||||
|
int top = viewLocation[1] - rootLocation[1];
|
||||||
|
return clampToRoot(root, new Bounds(left, top, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds clampToRoot(View root, Bounds bounds) {
|
||||||
|
if (root == null || bounds == null || root.getWidth() <= 0 || root.getHeight() <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int left = Math.max(0, bounds.left);
|
||||||
|
int top = Math.max(0, bounds.top);
|
||||||
|
int right = Math.min(root.getWidth(), bounds.left + bounds.width);
|
||||||
|
int bottom = Math.min(root.getHeight(), bounds.top + bounds.height);
|
||||||
|
if (right <= left || bottom <= top) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Bounds(left, top, right - left, bottom - top);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUsableRightAnchor(View root, Bounds bounds) {
|
||||||
|
if (root == null
|
||||||
|
|| bounds == null
|
||||||
|
|| bounds.width <= 0
|
||||||
|
|| bounds.height <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int right = right(bounds);
|
||||||
|
int bottom = bounds.top + bounds.height;
|
||||||
|
return bounds.left >= 0
|
||||||
|
&& right <= root.getWidth()
|
||||||
|
&& bounds.top >= 0
|
||||||
|
&& bottom <= root.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int right(Bounds bounds) {
|
||||||
|
return bounds.left + bounds.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArrayList<View> statusSourcesForRoot(View root, View excludedContainer) {
|
||||||
|
ArrayList<View> result = new ArrayList<>();
|
||||||
|
for (View source : STATUS_SOURCES.keySet()) {
|
||||||
|
if (!isUsableSource(root, source, excludedContainer)
|
||||||
|
|| !isDescendantOf(source, root)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!isStatusAnchorSource(STATUS_SOURCES.get(source))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(source);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDescendantOf(View view, View root) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
if (current == root) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Object parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRelated(View view, View other) {
|
||||||
|
return view != null
|
||||||
|
&& other != null
|
||||||
|
&& (isDescendantOf(view, other) || isDescendantOf(other, view));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isNotificationContainer(View view) {
|
||||||
|
String className = view != null ? view.getClass().getName() : "";
|
||||||
|
return className.contains("NotificationIconsOnlyContainer")
|
||||||
|
|| className.contains("NotificationIconContainer");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isOwnedRuntimeView(View view) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
Object tag = current.getTag();
|
||||||
|
if (tag instanceof String value && value.startsWith("statusbartweak.")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Object parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -165,6 +165,21 @@ final class ClockLayout {
|
|||||||
measured.height);
|
measured.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int centeredTextBaseline(TextView source, int containerHeight) {
|
||||||
|
if (source == null || source.getText() == null || source.getText().length() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TextView probe = new TextView(source.getContext());
|
||||||
|
probe.setLayoutParams(new ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||||||
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||||
|
ClockProxyRenderer.copyTextStyleIfChanged(source, probe);
|
||||||
|
MeasuredText measured = measureText(probe, source.getText());
|
||||||
|
int availableHeight = containerHeight > 0 ? containerHeight : measured.height;
|
||||||
|
int extraHeight = Math.max(0, availableHeight - measured.height);
|
||||||
|
return (extraHeight / 2) + measured.baseline;
|
||||||
|
}
|
||||||
|
|
||||||
private static ArrayList<MeasuredClockRow> positionRowsFromBaseline(
|
private static ArrayList<MeasuredClockRow> positionRowsFromBaseline(
|
||||||
ArrayList<MeasuredClockRow> measuredRows,
|
ArrayList<MeasuredClockRow> measuredRows,
|
||||||
int sourceBaselineY,
|
int sourceBaselineY,
|
||||||
|
|||||||
+296
-8
@@ -19,6 +19,8 @@ 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;
|
||||||
|
import se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle;
|
||||||
|
import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||||
|
|
||||||
public final class DebugBoundsOverlayController {
|
public final class DebugBoundsOverlayController {
|
||||||
@@ -31,8 +33,17 @@ public final class DebugBoundsOverlayController {
|
|||||||
private static final int COLOR_CLOCK = Color.argb(96, 64, 220, 96);
|
private static final int COLOR_CLOCK = Color.argb(96, 64, 220, 96);
|
||||||
private static final int COLOR_CHIP = Color.argb(112, 255, 0, 220);
|
private static final int COLOR_CHIP = Color.argb(112, 255, 0, 220);
|
||||||
private static final int COLOR_CUTOUT = Color.argb(112, 255, 180, 0);
|
private static final int COLOR_CUTOUT = Color.argb(112, 255, 180, 0);
|
||||||
|
private static final int COLOR_AOD_DERIVED_STATUSBAR = Color.argb(80, 255, 220, 0);
|
||||||
|
|
||||||
public boolean hasEnabledVisualizer(boolean layoutEnabled, SbtSettings settings) {
|
public boolean hasEnabledVisualizer(boolean layoutEnabled, SbtSettings settings) {
|
||||||
|
return hasEnabledVisualizer(layoutEnabled, settings, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEnabledVisualizer(
|
||||||
|
boolean layoutEnabled,
|
||||||
|
SbtSettings settings,
|
||||||
|
boolean aodStockVisualizersEnabled
|
||||||
|
) {
|
||||||
if (settings == null) {
|
if (settings == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -41,21 +52,44 @@ public final class DebugBoundsOverlayController {
|
|||||||
&& (settings.debugVisualizeNotificationContainer
|
&& (settings.debugVisualizeNotificationContainer
|
||||||
|| settings.debugVisualizeStatusContainer
|
|| settings.debugVisualizeStatusContainer
|
||||||
|| settings.debugVisualizeClockContainer
|
|| settings.debugVisualizeClockContainer
|
||||||
|| settings.debugVisualizeChipContainer));
|
|| settings.debugVisualizeChipContainer
|
||||||
|
|| (aodStockVisualizersEnabled && settings.debugVisualizeAodStockContainers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply(View root, boolean layoutEnabled, SbtSettings settings) {
|
public void apply(View root, boolean layoutEnabled, SbtSettings settings) {
|
||||||
|
apply(root, layoutEnabled, settings, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(
|
||||||
|
View root,
|
||||||
|
boolean layoutEnabled,
|
||||||
|
SbtSettings settings,
|
||||||
|
boolean aodStockVisualizersEnabled
|
||||||
|
) {
|
||||||
|
apply(root, layoutEnabled, settings, aodStockVisualizersEnabled, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(
|
||||||
|
View root,
|
||||||
|
boolean layoutEnabled,
|
||||||
|
SbtSettings settings,
|
||||||
|
boolean aodStockVisualizersEnabled,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
if (!(root instanceof ViewGroup parent) || settings == null) {
|
if (!(root instanceof ViewGroup parent) || settings == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!hasEnabledVisualizer(layoutEnabled, settings)) {
|
if (!hasEnabledVisualizer(layoutEnabled, settings, aodStockVisualizersEnabled)) {
|
||||||
removeOverlay(parent);
|
removeOverlays(parent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ArrayList<OverlaySpec> specs = new ArrayList<>();
|
ArrayList<OverlaySpec> specs = new ArrayList<>();
|
||||||
if (settings.debugVisualizeCameraCutout) {
|
if (settings.debugVisualizeCameraCutout) {
|
||||||
addCutoutSpecs(root, specs);
|
addCutoutSpecs(root, specs);
|
||||||
}
|
}
|
||||||
|
if (layoutEnabled && aodStockVisualizersEnabled && settings.debugVisualizeAodStockContainers) {
|
||||||
|
addAodSourceSpecs(root, settings, specs, scene);
|
||||||
|
}
|
||||||
if (layoutEnabled && settings.debugVisualizeNotificationContainer) {
|
if (layoutEnabled && settings.debugVisualizeNotificationContainer) {
|
||||||
addHostContainerSpecs(
|
addHostContainerSpecs(
|
||||||
root,
|
root,
|
||||||
@@ -84,10 +118,12 @@ public final class DebugBoundsOverlayController {
|
|||||||
specs);
|
specs);
|
||||||
}
|
}
|
||||||
if (specs.isEmpty()) {
|
if (specs.isEmpty()) {
|
||||||
removeOverlay(parent);
|
removeOverlays(parent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OverlayView host = ensureOverlay(parent);
|
ViewGroup overlayParent = overlayParent(root, parent, layoutEnabled, aodStockVisualizersEnabled, settings);
|
||||||
|
removeOverlayFromOtherParent(parent, overlayParent);
|
||||||
|
OverlayView host = ensureOverlay(overlayParent);
|
||||||
if (host == null) {
|
if (host == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -100,17 +136,183 @@ public final class DebugBoundsOverlayController {
|
|||||||
host.layout(0, 0, width, height);
|
host.layout(0, 0, width, height);
|
||||||
}
|
}
|
||||||
host.setSpecs(specs);
|
host.setSpecs(specs);
|
||||||
if (parent.getChildAt(parent.getChildCount() - 1) != host) {
|
if (overlayParent.getChildAt(overlayParent.getChildCount() - 1) != host) {
|
||||||
host.bringToFront();
|
host.bringToFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int sourceSignature(View root, boolean layoutEnabled, SbtSettings settings) {
|
||||||
|
return sourceSignature(root, layoutEnabled, settings, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sourceSignature(
|
||||||
|
View root,
|
||||||
|
boolean layoutEnabled,
|
||||||
|
SbtSettings settings,
|
||||||
|
boolean aodStockVisualizersEnabled
|
||||||
|
) {
|
||||||
|
return sourceSignature(root, layoutEnabled, settings, aodStockVisualizersEnabled, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int sourceSignature(
|
||||||
|
View root,
|
||||||
|
boolean layoutEnabled,
|
||||||
|
SbtSettings settings,
|
||||||
|
boolean aodStockVisualizersEnabled,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
|
if (!layoutEnabled || root == null || settings == null
|
||||||
|
|| !aodStockVisualizersEnabled
|
||||||
|
|| !settings.debugVisualizeAodStockContainers) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
ViewGroup notificationContainer = aodNotificationContainer(root, scene);
|
||||||
|
result = 31 * result + boundsSignature(
|
||||||
|
aodNotificationBounds(root, scene));
|
||||||
|
result = 31 * result + boundsSignature(liveAodStatusIconsBounds(root));
|
||||||
|
result = 31 * result + boundsSignature(
|
||||||
|
derivedAodStatusbarBounds(root, notificationContainer, settings, scene));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public void remove(View root) {
|
public void remove(View root) {
|
||||||
if (root instanceof ViewGroup parent) {
|
if (root instanceof ViewGroup parent) {
|
||||||
removeOverlay(parent);
|
removeOverlays(parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bringToFront(View root) {
|
||||||
|
if (!(root instanceof ViewGroup parent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bringOverlayToFront(parent);
|
||||||
|
bringOverlayToFront(directTaggedViewGroup(parent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST));
|
||||||
|
bringOverlayToFront(directTaggedViewGroup(parent, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST));
|
||||||
|
bringOverlayToFront(directTaggedViewGroup(parent, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST));
|
||||||
|
bringOverlayToFront(directTaggedViewGroup(parent, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST));
|
||||||
|
bringOverlayToFront(directTaggedViewGroup(parent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean addAodSourceSpecs(
|
||||||
|
View root,
|
||||||
|
SbtSettings settings,
|
||||||
|
ArrayList<OverlaySpec> specs,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
|
if (root == null || settings == null || specs == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean added = false;
|
||||||
|
ViewGroup notificationContainer = aodNotificationContainer(root, scene);
|
||||||
|
Bounds derivedStatusbar = derivedAodStatusbarBounds(root, notificationContainer, settings, scene);
|
||||||
|
if (derivedStatusbar != null) {
|
||||||
|
specs.add(new OverlaySpec(derivedStatusbar, COLOR_AOD_DERIVED_STATUSBAR, false));
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
added |= addBoundsSpec(
|
||||||
|
aodNotificationBounds(root, scene),
|
||||||
|
COLOR_NOTIFICATION,
|
||||||
|
true,
|
||||||
|
specs);
|
||||||
|
added |= addBoundsSpec(liveAodStatusIconsBounds(root), COLOR_STATUS, true, specs);
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean addBoundsSpec(Bounds bounds, int color, boolean fill, ArrayList<OverlaySpec> specs) {
|
||||||
|
if (bounds == null || bounds.width <= 0 || bounds.height <= 0 || specs == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
specs.add(new OverlaySpec(bounds, color, fill));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds derivedAodStatusbarBounds(
|
||||||
|
View root,
|
||||||
|
View notificationContainer,
|
||||||
|
SbtSettings settings,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
|
Bounds notificationBounds = aodNotificationBounds(root, scene);
|
||||||
|
Bounds statusBounds = liveAodStatusIconsBounds(root);
|
||||||
|
if (!isUsableAodAnchor(root, statusBounds)) {
|
||||||
|
statusBounds = overlayBounds(AodStatusbarSourceStore.statusBoundsForRoot(
|
||||||
|
root,
|
||||||
|
notificationContainer));
|
||||||
|
}
|
||||||
|
boolean hasNotification = isUsableAodAnchor(root, notificationBounds);
|
||||||
|
boolean hasStatus = isUsableAodAnchor(root, statusBounds);
|
||||||
|
if (!hasNotification && !hasStatus) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int left = hasNotification ? notificationBounds.left : 0;
|
||||||
|
int right = hasStatus ? statusBounds.left + statusBounds.width : root.getWidth();
|
||||||
|
left += settings != null ? settings.layoutPaddingLeftPx : 0;
|
||||||
|
right -= settings != null ? settings.layoutPaddingRightPx : 0;
|
||||||
|
int notificationBottom = hasNotification
|
||||||
|
? notificationBounds.top + notificationBounds.height
|
||||||
|
: 0;
|
||||||
|
int statusBottom = hasStatus ? statusBounds.top + statusBounds.height : 0;
|
||||||
|
int bottom = Math.max(notificationBottom, statusBottom);
|
||||||
|
if (right <= left || bottom <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Bounds(left, 0, right - left, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds aodNotificationBounds(View root, SceneKey scene) {
|
||||||
|
if (scene != null
|
||||||
|
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return overlayBounds(
|
||||||
|
LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForAodIconsRoot(root));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ViewGroup aodNotificationContainer(View root, SceneKey scene) {
|
||||||
|
if (scene != null
|
||||||
|
&& scene.notificationDisplayStyle() == NotificationDisplayStyle.CARDS) {
|
||||||
|
return LockscreenCardsNotificationIconSourceStore.sourceContainerForRoot(root);
|
||||||
|
}
|
||||||
|
return LockscreenCardsNotificationIconSourceStore.sourceContainerForAodIconsRoot(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isUsableAodAnchor(View root, Bounds bounds) {
|
||||||
|
if (root == null || bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int right = bounds.left + bounds.width;
|
||||||
|
int bottom = bounds.top + bounds.height;
|
||||||
|
return bounds.left >= 0
|
||||||
|
&& bounds.top >= 0
|
||||||
|
&& right <= root.getWidth()
|
||||||
|
&& bottom <= root.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int boundsSignature(Bounds bounds) {
|
||||||
|
if (bounds == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + bounds.left;
|
||||||
|
result = 31 * result + bounds.top;
|
||||||
|
result = 31 * result + bounds.width;
|
||||||
|
result = 31 * result + bounds.height;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
StatusBarLayoutSolver.Bounds bounds = 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) {
|
||||||
WindowInsets insets = root.getRootWindowInsets();
|
WindowInsets insets = root.getRootWindowInsets();
|
||||||
DisplayCutout cutout = insets != null ? insets.getDisplayCutout() : null;
|
DisplayCutout cutout = insets != null ? insets.getDisplayCutout() : null;
|
||||||
@@ -252,13 +454,94 @@ public final class DebugBoundsOverlayController {
|
|||||||
return host;
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ViewGroup overlayParent(
|
||||||
|
View root,
|
||||||
|
ViewGroup rootParent,
|
||||||
|
boolean layoutEnabled,
|
||||||
|
boolean aodStockVisualizersEnabled,
|
||||||
|
SbtSettings settings
|
||||||
|
) {
|
||||||
|
if (layoutEnabled
|
||||||
|
&& aodStockVisualizersEnabled
|
||||||
|
&& settings != null
|
||||||
|
&& settings.debugVisualizeAodStockContainers) {
|
||||||
|
View chipHost = findDirectTaggedChild(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST);
|
||||||
|
if (chipHost instanceof ViewGroup chipHostGroup) {
|
||||||
|
return chipHostGroup;
|
||||||
|
}
|
||||||
|
View statusHost = findDirectTaggedChild(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST);
|
||||||
|
if (statusHost instanceof ViewGroup statusHostGroup) {
|
||||||
|
return statusHostGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rootParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOverlayFromOtherParent(ViewGroup rootParent, ViewGroup overlayParent) {
|
||||||
|
if (rootParent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeOverlayIfParentDiffers(rootParent, overlayParent);
|
||||||
|
removeOverlayIfParentDiffers(
|
||||||
|
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST),
|
||||||
|
overlayParent);
|
||||||
|
removeOverlayIfParentDiffers(
|
||||||
|
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST),
|
||||||
|
overlayParent);
|
||||||
|
removeOverlayIfParentDiffers(
|
||||||
|
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST),
|
||||||
|
overlayParent);
|
||||||
|
removeOverlayIfParentDiffers(
|
||||||
|
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST),
|
||||||
|
overlayParent);
|
||||||
|
removeOverlayIfParentDiffers(
|
||||||
|
directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST),
|
||||||
|
overlayParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOverlays(ViewGroup rootParent) {
|
||||||
|
if (rootParent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
removeOverlay(rootParent);
|
||||||
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST));
|
||||||
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST));
|
||||||
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST));
|
||||||
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST));
|
||||||
|
removeOverlay(directTaggedViewGroup(rootParent, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeOverlayIfParentDiffers(ViewGroup parent, ViewGroup expectedParent) {
|
||||||
|
if (parent != null && parent != expectedParent) {
|
||||||
|
removeOverlay(parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void removeOverlay(ViewGroup parent) {
|
private void removeOverlay(ViewGroup parent) {
|
||||||
|
if (parent == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
View existing = findDirectTaggedChild(parent, TAG_OVERLAY_HOST);
|
View existing = findDirectTaggedChild(parent, TAG_OVERLAY_HOST);
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
parent.removeView(existing);
|
parent.removeView(existing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bringOverlayToFront(ViewGroup parent) {
|
||||||
|
if (parent == null || parent.getChildCount() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
View existing = findDirectTaggedChild(parent, TAG_OVERLAY_HOST);
|
||||||
|
if (existing != null && parent.getChildAt(parent.getChildCount() - 1) != existing) {
|
||||||
|
existing.bringToFront();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ViewGroup directTaggedViewGroup(ViewGroup parent, String tag) {
|
||||||
|
View view = findDirectTaggedChild(parent, tag);
|
||||||
|
return view instanceof ViewGroup group ? group : null;
|
||||||
|
}
|
||||||
|
|
||||||
private View findDirectTaggedChild(ViewGroup parent, String tag) {
|
private View findDirectTaggedChild(ViewGroup parent, String tag) {
|
||||||
if (parent == null || tag == null) {
|
if (parent == null || tag == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -352,7 +635,10 @@ public final class DebugBoundsOverlayController {
|
|||||||
return Math.max(min, Math.min(max, value));
|
return Math.max(min, Math.min(max, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
private record OverlaySpec(Bounds bounds, int color) {
|
private record OverlaySpec(Bounds bounds, int color, boolean fill) {
|
||||||
|
OverlaySpec(Bounds bounds, int color) {
|
||||||
|
this(bounds, color, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private record Bounds(int left, int top, int width, int height) {
|
private record Bounds(int left, int top, int width, int height) {
|
||||||
@@ -389,6 +675,8 @@ public final class DebugBoundsOverlayController {
|
|||||||
for (OverlaySpec spec : specs) {
|
for (OverlaySpec spec : specs) {
|
||||||
Bounds bounds = spec.bounds;
|
Bounds bounds = spec.bounds;
|
||||||
paint.setColor(spec.color);
|
paint.setColor(spec.color);
|
||||||
|
paint.setStyle(spec.fill ? Paint.Style.FILL : Paint.Style.STROKE);
|
||||||
|
paint.setStrokeWidth(Math.max(1f, getResources().getDisplayMetrics().density));
|
||||||
canvas.drawRect(
|
canvas.drawRect(
|
||||||
bounds.left,
|
bounds.left,
|
||||||
bounds.top,
|
bounds.top,
|
||||||
|
|||||||
+306
-2
@@ -2,6 +2,7 @@ package se.ajpanton.statusbartweak.runtime.render;
|
|||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -11,10 +12,17 @@ import java.util.Set;
|
|||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
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.shell.settings.AppIconRules;
|
||||||
|
|
||||||
public final class LockscreenCardsNotificationIconSourceStore {
|
public final class LockscreenCardsNotificationIconSourceStore {
|
||||||
private static final WeakHashMap<ViewGroup, ArrayList<SourceEntry>> SOURCES_BY_CONTAINER =
|
private static final WeakHashMap<ViewGroup, ArrayList<SourceEntry>> SOURCES_BY_CONTAINER =
|
||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
|
private static final WeakHashMap<ViewGroup, ArrayList<String>> PACKAGES_BY_CONTAINER =
|
||||||
|
new WeakHashMap<>();
|
||||||
|
private static final WeakHashMap<ViewGroup, ArrayList<View>> AOD_DRAWABLES_BY_CONTAINER =
|
||||||
|
new WeakHashMap<>();
|
||||||
|
private static final int VIRTUAL_ICON_SIZE_PX = 39;
|
||||||
|
|
||||||
private LockscreenCardsNotificationIconSourceStore() {
|
private LockscreenCardsNotificationIconSourceStore() {
|
||||||
}
|
}
|
||||||
@@ -41,12 +49,114 @@ public final class LockscreenCardsNotificationIconSourceStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean putPackages(ViewGroup container, ArrayList<String> packages) {
|
||||||
|
if (container == null || packages == null || packages.isEmpty()) {
|
||||||
|
if (container != null) {
|
||||||
|
return PACKAGES_BY_CONTAINER.remove(container) != null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ArrayList<String> valid = new ArrayList<>();
|
||||||
|
boolean hasValid = false;
|
||||||
|
for (String pkg : packages) {
|
||||||
|
if (AppIconRules.isValidPackageName(pkg)) {
|
||||||
|
valid.add(pkg);
|
||||||
|
hasValid = true;
|
||||||
|
} else {
|
||||||
|
valid.add(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasValid) {
|
||||||
|
return PACKAGES_BY_CONTAINER.remove(container) != null;
|
||||||
|
} else {
|
||||||
|
ArrayList<String> previous = PACKAGES_BY_CONTAINER.get(container);
|
||||||
|
if (previous != null && previous.equals(valid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PACKAGES_BY_CONTAINER.put(container, valid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean putAodDrawables(ViewGroup container, ArrayList<? extends View> views) {
|
||||||
|
if (container == null || views == null || views.isEmpty()) {
|
||||||
|
if (container != null) {
|
||||||
|
return AOD_DRAWABLES_BY_CONTAINER.remove(container) != null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ArrayList<View> valid = new ArrayList<>();
|
||||||
|
Set<View> seen = Collections.newSetFromMap(new IdentityHashMap<>());
|
||||||
|
for (View view : views) {
|
||||||
|
if (!(view instanceof ImageView imageView)
|
||||||
|
|| imageView.getDrawable() == null
|
||||||
|
|| !seen.add(view)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
valid.add(view);
|
||||||
|
}
|
||||||
|
if (valid.isEmpty()) {
|
||||||
|
return AOD_DRAWABLES_BY_CONTAINER.remove(container) != null;
|
||||||
|
} else {
|
||||||
|
ArrayList<View> previous = AOD_DRAWABLES_BY_CONTAINER.get(container);
|
||||||
|
if (sameViews(previous, valid)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AOD_DRAWABLES_BY_CONTAINER.put(container, valid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearAodSources() {
|
||||||
|
PACKAGES_BY_CONTAINER.clear();
|
||||||
|
AOD_DRAWABLES_BY_CONTAINER.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearAodSources(ViewGroup container) {
|
||||||
|
if (container == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PACKAGES_BY_CONTAINER.remove(container);
|
||||||
|
AOD_DRAWABLES_BY_CONTAINER.remove(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean sameViews(ArrayList<View> previous, ArrayList<View> current) {
|
||||||
|
if (previous == current) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (previous == null || current == null || previous.size() != current.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < previous.size(); i++) {
|
||||||
|
if (previous.get(i) != current.get(i)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static ArrayList<SnapshotSource> snapshotSources(ViewGroup container, View root) {
|
static ArrayList<SnapshotSource> snapshotSources(ViewGroup container, View root) {
|
||||||
ArrayList<SourceEntry> views = SOURCES_BY_CONTAINER.get(container);
|
|
||||||
ArrayList<SnapshotSource> result = new ArrayList<>();
|
ArrayList<SnapshotSource> result = new ArrayList<>();
|
||||||
if (views == null || views.isEmpty()) {
|
ArrayList<View> aodDrawables = AOD_DRAWABLES_BY_CONTAINER.get(container);
|
||||||
|
if (aodDrawables != null && !aodDrawables.isEmpty()) {
|
||||||
|
ArrayList<String> packages = PACKAGES_BY_CONTAINER.get(container);
|
||||||
|
Bounds containerBounds = sourceBoundsRelativeTo(root, container);
|
||||||
|
int top = containerBounds != null ? containerBounds.top : 0;
|
||||||
|
int size = VIRTUAL_ICON_SIZE_PX;
|
||||||
|
for (int i = 0; i < aodDrawables.size(); i++) {
|
||||||
|
View view = aodDrawables.get(i);
|
||||||
|
result.add(new SnapshotSource(
|
||||||
|
view,
|
||||||
|
SnapshotMode.NOTIFICATION_DRAWABLE,
|
||||||
|
aodDrawableKey(packages, i, view),
|
||||||
|
new Bounds(0, top, size, size)));
|
||||||
|
}
|
||||||
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ArrayList<SourceEntry> views = SOURCES_BY_CONTAINER.get(container);
|
||||||
|
if (views != null && !views.isEmpty()) {
|
||||||
int skipCards = visibleShelfStartIndex(container, views);
|
int skipCards = visibleShelfStartIndex(container, views);
|
||||||
HashSet<String> visibleCardKeys = visibleCardKeys(root, container);
|
HashSet<String> visibleCardKeys = visibleCardKeys(root, container);
|
||||||
for (int i = 0; i < views.size(); i++) {
|
for (int i = 0; i < views.size(); i++) {
|
||||||
@@ -68,8 +178,202 @@ public final class LockscreenCardsNotificationIconSourceStore {
|
|||||||
}
|
}
|
||||||
result.add(new SnapshotSource(view, SnapshotMode.NOTIFICATION_DRAWABLE, entry.key));
|
result.add(new SnapshotSource(view, SnapshotMode.NOTIFICATION_DRAWABLE, entry.key));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!result.isEmpty()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
ArrayList<String> packages = PACKAGES_BY_CONTAINER.get(container);
|
||||||
|
if (packages != null) {
|
||||||
|
Bounds containerBounds = sourceBoundsRelativeTo(root, container);
|
||||||
|
int top = containerBounds != null ? containerBounds.top : 0;
|
||||||
|
int size = VIRTUAL_ICON_SIZE_PX;
|
||||||
|
for (int i = 0; i < packages.size(); i++) {
|
||||||
|
String pkg = packages.get(i);
|
||||||
|
if (!AppIconRules.isValidPackageName(pkg)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(new SnapshotSource(
|
||||||
|
null,
|
||||||
|
SnapshotMode.APP_ICON,
|
||||||
|
pkg + "@aod" + i,
|
||||||
|
new Bounds(0, top, size, size)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String aodDrawableKey(ArrayList<String> packages, int index, View view) {
|
||||||
|
if (packages != null && index >= 0 && index < packages.size()) {
|
||||||
|
String pkg = packages.get(index);
|
||||||
|
if (AppIconRules.isValidPackageName(pkg)) {
|
||||||
|
return pkg + "@aod" + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "statusbartweak:aod_drawable@" + index + "@0x"
|
||||||
|
+ Integer.toHexString(System.identityHashCode(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArrayList<SnapshotSource> snapshotSourcesForRoot(View root) {
|
||||||
|
ArrayList<SnapshotSource> result = new ArrayList<>();
|
||||||
|
if (!(root instanceof ViewGroup rootGroup)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
ArrayList<View> stack = new ArrayList<>();
|
||||||
|
stack.add(rootGroup);
|
||||||
|
for (int i = 0; i < stack.size(); i++) {
|
||||||
|
View view = stack.get(i);
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
if (hasSources(group)) {
|
||||||
|
result = snapshotSources(group, root);
|
||||||
|
if (!result.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int child = 0; child < group.getChildCount(); child++) {
|
||||||
|
View childView = group.getChildAt(child);
|
||||||
|
if (childView != null) {
|
||||||
|
stack.add(childView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArrayList<SnapshotSource> snapshotSourcesForAodIconsRoot(View root) {
|
||||||
|
ArrayList<SnapshotSource> result = new ArrayList<>();
|
||||||
|
ViewGroup container = sourceContainerForAodIconsRoot(root);
|
||||||
|
if (container != null) {
|
||||||
|
result = snapshotSources(container, root);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ViewGroup sourceContainerForRoot(View root) {
|
||||||
|
ViewGroup container = sourceContainerForRoot(root, AOD_DRAWABLES_BY_CONTAINER.keySet());
|
||||||
|
if (container != null) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
container = sourceContainerForRoot(root, SOURCES_BY_CONTAINER.keySet());
|
||||||
|
if (container != null) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
return sourceContainerForRoot(root, PACKAGES_BY_CONTAINER.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
static ViewGroup sourceContainerForAodIconsRoot(View root) {
|
||||||
|
ViewGroup container = sourceContainerForRoot(
|
||||||
|
root,
|
||||||
|
AOD_DRAWABLES_BY_CONTAINER.keySet(),
|
||||||
|
true);
|
||||||
|
if (container != null) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
return sourceContainerForRoot(root, PACKAGES_BY_CONTAINER.keySet(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bounds sourceContainerBoundsForRoot(View root) {
|
||||||
|
ViewGroup container = sourceContainerForRoot(root);
|
||||||
|
Bounds bounds = sourceBoundsRelativeTo(root, container);
|
||||||
|
if (isZeroSizeDotContainer(container, bounds)) {
|
||||||
|
return new Bounds(bounds.left, bounds.top, VIRTUAL_ICON_SIZE_PX, VIRTUAL_ICON_SIZE_PX);
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Bounds sourceContainerBoundsForAodIconsRoot(View root) {
|
||||||
|
ViewGroup container = sourceContainerForAodIconsRoot(root);
|
||||||
|
Bounds bounds = sourceBoundsRelativeTo(root, container);
|
||||||
|
if (isZeroSizeDotContainer(container, bounds)) {
|
||||||
|
return new Bounds(bounds.left, bounds.top, VIRTUAL_ICON_SIZE_PX, VIRTUAL_ICON_SIZE_PX);
|
||||||
|
}
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds sourceBoundsRelativeTo(View root, ViewGroup container) {
|
||||||
|
Bounds bounds = container != null ? ViewGeometry.boundsRelativeTo(root, container) : null;
|
||||||
|
if (bounds == null || isZeroSizeDotContainer(container, bounds)) {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
if (!hasAodSources(container) || bounds.height <= 0) {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
// Samsung's AOD icon-only container can temporarily expand vertically;
|
||||||
|
// downstream layout cares about the icon row, not that outer transition box.
|
||||||
|
int centerY = bounds.top + bounds.height / 2;
|
||||||
|
int top = centerY - VIRTUAL_ICON_SIZE_PX / 2;
|
||||||
|
return new Bounds(bounds.left, top, bounds.width, VIRTUAL_ICON_SIZE_PX);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasAodSources(ViewGroup container) {
|
||||||
|
return container != null
|
||||||
|
&& (AOD_DRAWABLES_BY_CONTAINER.containsKey(container)
|
||||||
|
|| PACKAGES_BY_CONTAINER.containsKey(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isZeroSizeDotContainer(ViewGroup container, Bounds bounds) {
|
||||||
|
if (container == null
|
||||||
|
|| bounds == null
|
||||||
|
|| bounds.width > 0
|
||||||
|
|| bounds.height > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return "notification_dot_container".equals(resolveIdName(container));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ViewGroup sourceContainerForRoot(
|
||||||
|
View root,
|
||||||
|
Set<ViewGroup> containers
|
||||||
|
) {
|
||||||
|
return sourceContainerForRoot(root, containers, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ViewGroup sourceContainerForRoot(
|
||||||
|
View root,
|
||||||
|
Set<ViewGroup> containers,
|
||||||
|
boolean iconOnlyContainerRequired
|
||||||
|
) {
|
||||||
|
if (root == null || containers == null || containers.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (ViewGroup container : containers) {
|
||||||
|
if (container != null
|
||||||
|
&& container.isAttachedToWindow()
|
||||||
|
&& isDescendantOf(container, root)
|
||||||
|
&& (!iconOnlyContainerRequired || isAodIconOnlyContainer(container))) {
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isAodIconOnlyContainer(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String idName = resolveIdName(view);
|
||||||
|
return "keyguard_icononly_container_view".equals(idName)
|
||||||
|
|| "notification_icononly_container".equals(idName)
|
||||||
|
|| "notification_icononly_area".equals(idName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDescendantOf(View view, View root) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
if (current == root) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Object parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean hasSources(ViewGroup container) {
|
||||||
|
return SOURCES_BY_CONTAINER.containsKey(container)
|
||||||
|
|| AOD_DRAWABLES_BY_CONTAINER.containsKey(container)
|
||||||
|
|| PACKAGES_BY_CONTAINER.containsKey(container);
|
||||||
|
}
|
||||||
|
|
||||||
private static HashSet<String> visibleCardKeys(View root, View shelf) {
|
private static HashSet<String> visibleCardKeys(View root, View shelf) {
|
||||||
HashSet<String> result = new HashSet<>();
|
HashSet<String> result = new HashSet<>();
|
||||||
|
|||||||
+124
-27
@@ -30,6 +30,7 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
|
|
||||||
private final SnapshotRenderer renderer = new SnapshotRenderer(false, false, false);
|
private final SnapshotRenderer renderer = new SnapshotRenderer(false, false, false);
|
||||||
private final WeakHashMap<ViewGroup, ArrayList<View>> pillViewsByHost = new WeakHashMap<>();
|
private final WeakHashMap<ViewGroup, ArrayList<View>> pillViewsByHost = new WeakHashMap<>();
|
||||||
|
private final WeakHashMap<View, Integer> aodInitialStatusbarHeightByRoot = new WeakHashMap<>();
|
||||||
private final NotificationSeenAppReporter seenAppReporter = new NotificationSeenAppReporter();
|
private final NotificationSeenAppReporter seenAppReporter = new NotificationSeenAppReporter();
|
||||||
|
|
||||||
public RenderResult render(
|
public RenderResult render(
|
||||||
@@ -38,28 +39,43 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
SbtSettings settings,
|
SbtSettings settings,
|
||||||
SceneKey scene
|
SceneKey scene
|
||||||
) {
|
) {
|
||||||
|
if (root != null && (scene == null || !scene.isAod())) {
|
||||||
|
aodInitialStatusbarHeightByRoot.remove(root);
|
||||||
|
}
|
||||||
if (root == null
|
if (root == null
|
||||||
|| host == null
|
|| host == null
|
||||||
|| settings == null
|
|| settings == null
|
||||||
|| scene == null
|
|| scene == null
|
||||||
|| !scene.isLockscreen()
|
|
||||||
|| scene.notificationDisplayStyle() != NotificationDisplayStyle.CARDS
|
|| scene.notificationDisplayStyle() != NotificationDisplayStyle.CARDS
|
||||||
|| settings.cardsLockMaxRows <= 0) {
|
|| !(scene.isLockscreen() || scene.isAod())
|
||||||
|
|| maxRows(settings, scene) <= 0) {
|
||||||
clear(host);
|
clear(host);
|
||||||
return RenderResult.empty();
|
return RenderResult.empty();
|
||||||
}
|
}
|
||||||
ViewGroup sourceRoot = findSourceRoot(root);
|
ViewGroup sourceRoot = scene.isAod()
|
||||||
if (sourceRoot == null) {
|
? LockscreenCardsNotificationIconSourceStore.sourceContainerForRoot(root)
|
||||||
|
: findSourceRoot(root);
|
||||||
|
if (sourceRoot == null && scene.isAod()) {
|
||||||
|
sourceRoot = findSourceRoot(root);
|
||||||
|
}
|
||||||
|
if (sourceRoot == null && !scene.isAod()) {
|
||||||
clear(host);
|
clear(host);
|
||||||
return RenderResult.empty();
|
return RenderResult.empty();
|
||||||
}
|
}
|
||||||
if (hasHiddenShelfAncestor(sourceRoot, root)) {
|
if (!scene.isAod() && hasHiddenShelfAncestor(sourceRoot, root)) {
|
||||||
clear(host);
|
clear(host);
|
||||||
return RenderResult.empty();
|
return RenderResult.empty();
|
||||||
}
|
}
|
||||||
|
if (sourceRoot != null) {
|
||||||
syncHostAnimation(host, sourceRoot);
|
syncHostAnimation(host, sourceRoot);
|
||||||
ArrayList<SnapshotSource> sources = LockscreenCardsNotificationIconSourceStore.snapshotSources(sourceRoot, root);
|
}
|
||||||
if (sources.isEmpty()) {
|
ArrayList<SnapshotSource> sources = scene.isAod()
|
||||||
|
? LockscreenCardsNotificationIconSourceStore.snapshotSourcesForRoot(root)
|
||||||
|
: new ArrayList<>();
|
||||||
|
if (sources.isEmpty() && sourceRoot != null) {
|
||||||
|
sources = LockscreenCardsNotificationIconSourceStore.snapshotSources(sourceRoot, root);
|
||||||
|
}
|
||||||
|
if (sources.isEmpty() && sourceRoot != null) {
|
||||||
sources = collectSources(sourceRoot);
|
sources = collectSources(sourceRoot);
|
||||||
}
|
}
|
||||||
if (sources.isEmpty()) {
|
if (sources.isEmpty()) {
|
||||||
@@ -72,8 +88,24 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
unfilteredPlacements,
|
unfilteredPlacements,
|
||||||
settings,
|
settings,
|
||||||
scene);
|
scene);
|
||||||
StripLayout layout = layoutPlacements(root, sourceRoot, placements, settings);
|
Bounds sourceBounds = scene.isAod()
|
||||||
renderPills(host, layout.rowBounds, resolvePillColor(sourceRoot));
|
? LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForRoot(root)
|
||||||
|
: null;
|
||||||
|
if (sourceBounds == null && sourceRoot != null) {
|
||||||
|
sourceBounds = ViewGeometry.boundsRelativeTo(root, sourceRoot);
|
||||||
|
}
|
||||||
|
int statusbarHeight = statusbarHeight(root, sourceBounds, scene);
|
||||||
|
int iconHeight = iconHeightPx(
|
||||||
|
statusbarHeight,
|
||||||
|
cardsIconHeightSteps(settings, scene),
|
||||||
|
representativeHeight(placements));
|
||||||
|
StripLayout layout = layoutPlacements(root, sourceBounds, placements, settings, scene, iconHeight);
|
||||||
|
if (scene.isAod()) {
|
||||||
|
clearPills(host);
|
||||||
|
} else {
|
||||||
|
renderPills(host, layout.rowBounds,
|
||||||
|
sourceRoot != null ? resolvePillColor(sourceRoot) : DEFAULT_PILL_COLOR);
|
||||||
|
}
|
||||||
Bounds renderedBounds = renderer.renderPlacements(host, layout.placements);
|
Bounds renderedBounds = renderer.renderPlacements(host, layout.placements);
|
||||||
return new RenderResult(sourceRoot, renderedBounds);
|
return new RenderResult(sourceRoot, renderedBounds);
|
||||||
}
|
}
|
||||||
@@ -85,6 +117,12 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
|
|
||||||
public void clearAll() {
|
public void clearAll() {
|
||||||
renderer.clearAll();
|
renderer.clearAll();
|
||||||
|
ArrayList<ViewGroup> hosts = new ArrayList<>(pillViewsByHost.keySet());
|
||||||
|
for (ViewGroup host : hosts) {
|
||||||
|
clearPills(host);
|
||||||
|
}
|
||||||
|
pillViewsByHost.clear();
|
||||||
|
aodInitialStatusbarHeightByRoot.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ViewGroup findSourceRoot(View root) {
|
private ViewGroup findSourceRoot(View root) {
|
||||||
@@ -172,17 +210,19 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
|
|
||||||
private StripLayout layoutPlacements(
|
private StripLayout layoutPlacements(
|
||||||
View root,
|
View root,
|
||||||
View sourceRoot,
|
Bounds sourceBounds,
|
||||||
ArrayList<SnapshotPlacement> placements,
|
ArrayList<SnapshotPlacement> placements,
|
||||||
SbtSettings settings
|
SbtSettings settings,
|
||||||
|
SceneKey scene,
|
||||||
|
int iconHeight
|
||||||
) {
|
) {
|
||||||
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
||||||
ArrayList<Bounds> rowBounds = new ArrayList<>();
|
ArrayList<Bounds> rowBounds = new ArrayList<>();
|
||||||
if (placements == null || placements.isEmpty()) {
|
if (placements == null || placements.isEmpty()) {
|
||||||
return new StripLayout(result, rowBounds);
|
return new StripLayout(result, rowBounds);
|
||||||
}
|
}
|
||||||
int maxPerRow = Math.max(1, settings.cardsLockMaxIconsPerRow);
|
int maxPerRow = Math.max(1, maxIconsPerRow(settings, scene));
|
||||||
int maxRows = Math.max(0, settings.cardsLockMaxRows);
|
int maxRows = Math.max(0, maxRows(settings, scene));
|
||||||
int capacity = maxPerRow * maxRows;
|
int capacity = maxPerRow * maxRows;
|
||||||
if (capacity <= 0) {
|
if (capacity <= 0) {
|
||||||
return new StripLayout(result, rowBounds);
|
return new StripLayout(result, rowBounds);
|
||||||
@@ -190,18 +230,16 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
boolean showDot = placements.size() > capacity;
|
boolean showDot = placements.size() > capacity;
|
||||||
int iconSlots = showDot ? Math.max(0, capacity - 1) : Math.min(capacity, placements.size());
|
int iconSlots = showDot ? Math.max(0, capacity - 1) : Math.min(capacity, placements.size());
|
||||||
int visible = iconSlots + (showDot ? 1 : 0);
|
int visible = iconSlots + (showDot ? 1 : 0);
|
||||||
int iconHeight = representativeHeight(placements);
|
int iconWidth = iconHeight;
|
||||||
int iconWidth = representativeWidth(placements, iconHeight);
|
|
||||||
Bounds sourceBounds = ViewGeometry.boundsRelativeTo(root, sourceRoot);
|
|
||||||
int top = sourceBounds != null ? sourceBounds.top : placements.get(0).bounds.top;
|
int top = sourceBounds != null ? sourceBounds.top : placements.get(0).bounds.top;
|
||||||
int centerX = sourceBounds != null
|
int centerX = sourceBounds != null
|
||||||
? sourceBounds.left + sourceBounds.width / 2
|
? sourceBounds.left + sourceBounds.width / 2
|
||||||
: root.getWidth() / 2;
|
: root.getWidth() / 2;
|
||||||
int availableWidth = settings.cardsLockLimitToWidth
|
int availableWidth = limitToWidth(settings, scene)
|
||||||
? Math.max(0, root.getWidth())
|
? Math.max(0, root.getWidth())
|
||||||
: Integer.MAX_VALUE;
|
: Integer.MAX_VALUE;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int[] rowCounts = rowCounts(visible, maxPerRow, maxRows, settings.cardsLockEvenDistribution);
|
int[] rowCounts = rowCounts(visible, maxPerRow, maxRows, evenDistribution(settings, scene));
|
||||||
int dotColor = dotColor(placements);
|
int dotColor = dotColor(placements);
|
||||||
int rowGap = dp(root, 8);
|
int rowGap = dp(root, 8);
|
||||||
for (int row = 0; row < rowCounts.length && index < visible; row++) {
|
for (int row = 0; row < rowCounts.length && index < visible; row++) {
|
||||||
@@ -236,6 +274,30 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
return new StripLayout(result, rowBounds);
|
return new StripLayout(result, rowBounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int maxIconsPerRow(SbtSettings settings, SceneKey scene) {
|
||||||
|
return scene != null && scene.isAod()
|
||||||
|
? settings.cardsAodMaxIconsPerRow
|
||||||
|
: settings.cardsLockMaxIconsPerRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int maxRows(SbtSettings settings, SceneKey scene) {
|
||||||
|
return scene != null && scene.isAod()
|
||||||
|
? settings.cardsAodMaxRows
|
||||||
|
: settings.cardsLockMaxRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean evenDistribution(SbtSettings settings, SceneKey scene) {
|
||||||
|
return scene != null && scene.isAod()
|
||||||
|
? settings.cardsAodEvenDistribution
|
||||||
|
: settings.cardsLockEvenDistribution;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean limitToWidth(SbtSettings settings, SceneKey scene) {
|
||||||
|
return scene != null && scene.isAod()
|
||||||
|
? settings.cardsAodLimitToWidth
|
||||||
|
: settings.cardsLockLimitToWidth;
|
||||||
|
}
|
||||||
|
|
||||||
private int[] rowCounts(
|
private int[] rowCounts(
|
||||||
int slots,
|
int slots,
|
||||||
int maxPerRow,
|
int maxPerRow,
|
||||||
@@ -459,15 +521,6 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int representativeWidth(ArrayList<SnapshotPlacement> placements, int fallback) {
|
|
||||||
for (SnapshotPlacement placement : placements) {
|
|
||||||
if (placement != null && placement.bounds != null && placement.bounds.width > 0) {
|
|
||||||
return placement.bounds.width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Math.max(1, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int representativeHeight(ArrayList<SnapshotPlacement> placements) {
|
private int representativeHeight(ArrayList<SnapshotPlacement> placements) {
|
||||||
for (SnapshotPlacement placement : placements) {
|
for (SnapshotPlacement placement : placements) {
|
||||||
if (placement != null && placement.bounds != null && placement.bounds.height > 0) {
|
if (placement != null && placement.bounds != null && placement.bounds.height > 0) {
|
||||||
@@ -477,6 +530,50 @@ public final class LockscreenCardsNotificationStripRenderer {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int cardsIconHeightSteps(SbtSettings settings, SceneKey scene) {
|
||||||
|
return scene != null && scene.isAod()
|
||||||
|
? settings.cardsAodIconHeightSteps
|
||||||
|
: settings.cardsLockIconHeightSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int iconHeightPx(int statusbarHeight, int steps, int fallbackHeight) {
|
||||||
|
if (statusbarHeight <= 0) {
|
||||||
|
return Math.max(1, fallbackHeight);
|
||||||
|
}
|
||||||
|
return Math.max(1, Math.round((float) statusbarHeight * Math.max(1, steps) / 100f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int statusbarHeight(View root, Bounds sourceBounds, SceneKey scene) {
|
||||||
|
int sharedHeight = StatusbarHeightStore.get(root);
|
||||||
|
if (sharedHeight > 0) {
|
||||||
|
return sharedHeight;
|
||||||
|
}
|
||||||
|
Bounds statusBounds = StatusbarHeightSource.bounds(root, scene, null);
|
||||||
|
if (statusBounds != null && statusBounds.top >= 0 && statusBounds.height > 0) {
|
||||||
|
int height = Math.max(1, statusBounds.top + statusBounds.height);
|
||||||
|
if (scene != null && scene.isAod() && root != null) {
|
||||||
|
Integer stored = aodInitialStatusbarHeightByRoot.get(root);
|
||||||
|
if (stored != null && stored > 0) {
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
aodInitialStatusbarHeightByRoot.put(root, height);
|
||||||
|
} else {
|
||||||
|
StatusbarHeightStore.put(root, height);
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
if (scene != null && scene.isAod() && root != null) {
|
||||||
|
Integer stored = aodInitialStatusbarHeightByRoot.get(root);
|
||||||
|
if (stored != null && stored > 0) {
|
||||||
|
return stored;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sourceBounds != null && sourceBounds.top >= 0 && sourceBounds.height > 0) {
|
||||||
|
return Math.max(1, sourceBounds.top + sourceBounds.height);
|
||||||
|
}
|
||||||
|
return Math.max(1, root != null ? root.getHeight() : 1);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isShelfIconContainer(View view) {
|
private boolean isShelfIconContainer(View view) {
|
||||||
String className = view.getClass().getName();
|
String className = view.getClass().getName();
|
||||||
return className.contains("SecShelfNotificationIconContainer");
|
return className.contains("SecShelfNotificationIconContainer");
|
||||||
|
|||||||
+21
-4
@@ -6,24 +6,34 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||||
|
|
||||||
final class NotificationSeenAppReporter {
|
final class NotificationSeenAppReporter {
|
||||||
private static final long MIN_REPORT_INTERVAL_MS = 500L;
|
private static final long MIN_REPORT_INTERVAL_MS = 60_000L;
|
||||||
|
|
||||||
private final Map<String, Long> lastReportedMs = new HashMap<>();
|
private final Map<String, Long> lastReportedMs = new HashMap<>();
|
||||||
|
private final Map<String, HashSet<String>> activeKeysByPackage = new HashMap<>();
|
||||||
|
|
||||||
void report(Context context, ArrayList<SnapshotPlacement> placements) {
|
void report(Context context, ArrayList<SnapshotPlacement> placements) {
|
||||||
if (context == null || placements == null || placements.isEmpty()) {
|
if (context == null || placements == null || placements.isEmpty()) {
|
||||||
|
activeKeysByPackage.clear();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
HashMap<String, HashSet<String>> currentKeysByPackage = new HashMap<>();
|
||||||
HashSet<String> reportedThisPass = new HashSet<>();
|
HashSet<String> reportedThisPass = new HashSet<>();
|
||||||
for (SnapshotPlacement placement : placements) {
|
for (SnapshotPlacement placement : placements) {
|
||||||
String packageName = SnapshotIconFilter.notificationPackage(
|
String key = placement != null ? placement.key : null;
|
||||||
placement != null ? placement.key : null);
|
String packageName = SnapshotIconFilter.notificationPackage(key);
|
||||||
if (packageName == null || !reportedThisPass.add(packageName)) {
|
if (packageName == null || key == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
currentKeysByPackage
|
||||||
|
.computeIfAbsent(packageName, ignored -> new HashSet<>())
|
||||||
|
.add(key);
|
||||||
|
if (wasAlreadyActive(packageName, key) || !reportedThisPass.add(packageName)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Long lastReported = lastReportedMs.get(packageName);
|
Long lastReported = lastReportedMs.get(packageName);
|
||||||
@@ -33,5 +43,12 @@ final class NotificationSeenAppReporter {
|
|||||||
lastReportedMs.put(packageName, now);
|
lastReportedMs.put(packageName, now);
|
||||||
SbtSettings.noteSeenIconApp(context, packageName, now);
|
SbtSettings.noteSeenIconApp(context, packageName, now);
|
||||||
}
|
}
|
||||||
|
activeKeysByPackage.clear();
|
||||||
|
activeKeysByPackage.putAll(currentKeysByPackage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean wasAlreadyActive(String packageName, String key) {
|
||||||
|
Set<String> activeKeys = activeKeysByPackage.get(packageName);
|
||||||
|
return activeKeys != null && activeKeys.contains(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -28,6 +28,8 @@ public final class OwnedIconHostManager {
|
|||||||
"statusbartweak.unlocked.chip.host";
|
"statusbartweak.unlocked.chip.host";
|
||||||
public static final String TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST =
|
public static final String TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST =
|
||||||
"statusbartweak.lockscreen.cards.notification.host";
|
"statusbartweak.lockscreen.cards.notification.host";
|
||||||
|
public static final String TAG_AOD_CARDS_NOTIFICATION_HOST =
|
||||||
|
"statusbartweak.aod.cards.notification.host";
|
||||||
private static final String[] UNLOCKED_HOST_ORDER = {
|
private static final String[] UNLOCKED_HOST_ORDER = {
|
||||||
TAG_UNLOCKED_STATUS_HOST,
|
TAG_UNLOCKED_STATUS_HOST,
|
||||||
TAG_UNLOCKED_NOTIFICATION_HOST,
|
TAG_UNLOCKED_NOTIFICATION_HOST,
|
||||||
@@ -60,6 +62,10 @@ public final class OwnedIconHostManager {
|
|||||||
return ensureHost(root, TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST);
|
return ensureHost(root, TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FrameLayout ensureAodCardsNotificationHost(View root) {
|
||||||
|
return ensureHost(root, TAG_AOD_CARDS_NOTIFICATION_HOST);
|
||||||
|
}
|
||||||
|
|
||||||
public FrameLayout ensureHost(View root, String tag) {
|
public FrameLayout ensureHost(View root, String tag) {
|
||||||
Objects.requireNonNull(tag, "tag");
|
Objects.requireNonNull(tag, "tag");
|
||||||
if (!(root instanceof ViewGroup parent)) {
|
if (!(root instanceof ViewGroup parent)) {
|
||||||
@@ -99,6 +105,7 @@ public final class OwnedIconHostManager {
|
|||||||
removeHost(root, TAG_UNLOCKED_CARRIER_HOST);
|
removeHost(root, TAG_UNLOCKED_CARRIER_HOST);
|
||||||
removeHost(root, TAG_UNLOCKED_CHIP_HOST);
|
removeHost(root, TAG_UNLOCKED_CHIP_HOST);
|
||||||
removeHost(root, TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST);
|
removeHost(root, TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST);
|
||||||
|
removeHost(root, TAG_AOD_CARDS_NOTIFICATION_HOST);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUnlockedHostsVisible(View root, boolean visible) {
|
public void setUnlockedHostsVisible(View root, boolean visible) {
|
||||||
@@ -130,7 +137,8 @@ public final class OwnedIconHostManager {
|
|||||||
|| TAG_UNLOCKED_CLOCK_HOST.equals(tag)
|
|| TAG_UNLOCKED_CLOCK_HOST.equals(tag)
|
||||||
|| TAG_UNLOCKED_CARRIER_HOST.equals(tag)
|
|| TAG_UNLOCKED_CARRIER_HOST.equals(tag)
|
||||||
|| TAG_UNLOCKED_CHIP_HOST.equals(tag)
|
|| TAG_UNLOCKED_CHIP_HOST.equals(tag)
|
||||||
|| TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST.equals(tag);
|
|| TAG_LOCKSCREEN_CARDS_NOTIFICATION_HOST.equals(tag)
|
||||||
|
|| TAG_AOD_CARDS_NOTIFICATION_HOST.equals(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FrameLayout findDirectHost(ViewGroup parent, String tag) {
|
private FrameLayout findDirectHost(ViewGroup parent, String tag) {
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ final class SnapshotIconFilter {
|
|||||||
append(sb, placement.key);
|
append(sb, placement.key);
|
||||||
View view = placement.source != null ? placement.source.view() : null;
|
View view = placement.source != null ? placement.source.view() : null;
|
||||||
appendViewText(sb, view);
|
appendViewText(sb, view);
|
||||||
|
appendAncestorViewText(sb, view);
|
||||||
return sb.toString().toLowerCase(Locale.ROOT);
|
return sb.toString().toLowerCase(Locale.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +170,15 @@ final class SnapshotIconFilter {
|
|||||||
append(sb, contentDescription != null ? contentDescription.toString() : null);
|
append(sb, contentDescription != null ? contentDescription.toString() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void appendAncestorViewText(StringBuilder sb, View view) {
|
||||||
|
Object parent = view != null ? view.getParent() : null;
|
||||||
|
int depth = 0;
|
||||||
|
while (parent instanceof View parentView && depth++ < 4) {
|
||||||
|
appendViewText(sb, parentView);
|
||||||
|
parent = parentView.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ArrayList<String> statusSlots(String matchText) {
|
private static ArrayList<String> statusSlots(String matchText) {
|
||||||
ArrayList<String> slots = new ArrayList<>();
|
ArrayList<String> slots = new ArrayList<>();
|
||||||
add(slots, normalizedSlot(matchText));
|
add(slots, normalizedSlot(matchText));
|
||||||
|
|||||||
@@ -12,16 +12,23 @@ import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bou
|
|||||||
record SnapshotSource(
|
record SnapshotSource(
|
||||||
View view,
|
View view,
|
||||||
SnapshotMode mode,
|
SnapshotMode mode,
|
||||||
String keyHint
|
String keyHint,
|
||||||
|
Bounds boundsOverride
|
||||||
) {
|
) {
|
||||||
|
SnapshotSource(View view, SnapshotMode mode, String keyHint) {
|
||||||
|
this(view, mode, keyHint, null);
|
||||||
|
}
|
||||||
|
|
||||||
SnapshotSource(View view, SnapshotMode mode) {
|
SnapshotSource(View view, SnapshotMode mode) {
|
||||||
this(view, mode, null);
|
this(view, mode, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SnapshotMode {
|
enum SnapshotMode {
|
||||||
VIEW,
|
VIEW,
|
||||||
NOTIFICATION_DRAWABLE
|
STATUS_CHIP,
|
||||||
|
NOTIFICATION_DRAWABLE,
|
||||||
|
APP_ICON
|
||||||
}
|
}
|
||||||
|
|
||||||
final class SnapshotKeys {
|
final class SnapshotKeys {
|
||||||
@@ -43,6 +50,7 @@ final class SnapshotPlacement {
|
|||||||
final HeldSignal heldSignal;
|
final HeldSignal heldSignal;
|
||||||
final Bounds contentBounds;
|
final Bounds contentBounds;
|
||||||
final int sourceOffsetX;
|
final int sourceOffsetX;
|
||||||
|
final Bounds sourceRenderBounds;
|
||||||
|
|
||||||
SnapshotPlacement(
|
SnapshotPlacement(
|
||||||
SnapshotSource source,
|
SnapshotSource source,
|
||||||
@@ -63,7 +71,8 @@ final class SnapshotPlacement {
|
|||||||
Color.WHITE,
|
Color.WHITE,
|
||||||
heldSignal,
|
heldSignal,
|
||||||
contentBounds,
|
contentBounds,
|
||||||
sourceOffsetX);
|
sourceOffsetX,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapshotPlacement(
|
SnapshotPlacement(
|
||||||
@@ -76,6 +85,31 @@ final class SnapshotPlacement {
|
|||||||
HeldSignal heldSignal,
|
HeldSignal heldSignal,
|
||||||
Bounds contentBounds,
|
Bounds contentBounds,
|
||||||
int sourceOffsetX
|
int sourceOffsetX
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
source,
|
||||||
|
bounds,
|
||||||
|
key,
|
||||||
|
signal,
|
||||||
|
overflowDot,
|
||||||
|
overflowDotColor,
|
||||||
|
heldSignal,
|
||||||
|
contentBounds,
|
||||||
|
sourceOffsetX,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapshotPlacement(
|
||||||
|
SnapshotSource source,
|
||||||
|
Bounds bounds,
|
||||||
|
String key,
|
||||||
|
boolean signal,
|
||||||
|
boolean overflowDot,
|
||||||
|
int overflowDotColor,
|
||||||
|
HeldSignal heldSignal,
|
||||||
|
Bounds contentBounds,
|
||||||
|
int sourceOffsetX,
|
||||||
|
Bounds sourceRenderBounds
|
||||||
) {
|
) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
@@ -86,6 +120,7 @@ final class SnapshotPlacement {
|
|||||||
this.heldSignal = heldSignal;
|
this.heldSignal = heldSignal;
|
||||||
this.contentBounds = contentBounds;
|
this.contentBounds = contentBounds;
|
||||||
this.sourceOffsetX = sourceOffsetX;
|
this.sourceOffsetX = sourceOffsetX;
|
||||||
|
this.sourceRenderBounds = sourceRenderBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
SnapshotSource source() {
|
SnapshotSource source() {
|
||||||
@@ -123,6 +158,10 @@ final class SnapshotPlacement {
|
|||||||
int sourceOffsetX() {
|
int sourceOffsetX() {
|
||||||
return sourceOffsetX;
|
return sourceOffsetX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bounds sourceRenderBounds() {
|
||||||
|
return sourceRenderBounds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
record BitmapResult(Bitmap bitmap, boolean created) {
|
record BitmapResult(Bitmap bitmap, boolean created) {
|
||||||
@@ -130,14 +169,13 @@ record BitmapResult(Bitmap bitmap, boolean created) {
|
|||||||
|
|
||||||
record SnapshotRenderState(
|
record SnapshotRenderState(
|
||||||
String key,
|
String key,
|
||||||
int left,
|
|
||||||
int top,
|
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
boolean signal,
|
boolean signal,
|
||||||
boolean overflowDot,
|
boolean overflowDot,
|
||||||
int overflowDotColor,
|
int overflowDotColor,
|
||||||
int sourceOffsetX,
|
int sourceOffsetX,
|
||||||
|
int sourceRenderBoundsSignature,
|
||||||
String heldSignalKey,
|
String heldSignalKey,
|
||||||
int heldBitmapId,
|
int heldBitmapId,
|
||||||
SnapshotMode sourceMode,
|
SnapshotMode sourceMode,
|
||||||
|
|||||||
+409
-11
@@ -1,5 +1,7 @@
|
|||||||
package se.ajpanton.statusbartweak.runtime.render;
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
@@ -20,6 +22,7 @@ import java.util.Comparator;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
|
import se.ajpanton.statusbartweak.runtime.hooks.ReflectionSupport;
|
||||||
@@ -35,6 +38,8 @@ final class SnapshotRenderer {
|
|||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
private final WeakHashMap<ImageView, SnapshotRenderState> statesByProxy =
|
private final WeakHashMap<ImageView, SnapshotRenderState> statesByProxy =
|
||||||
new WeakHashMap<>();
|
new WeakHashMap<>();
|
||||||
|
private final WeakHashMap<View, SourceSignatureCache> sourceSignaturesByView =
|
||||||
|
new WeakHashMap<>();
|
||||||
private final LinkedHashMap<String, HeldSignal> heldSignals = new LinkedHashMap<>();
|
private final LinkedHashMap<String, HeldSignal> heldSignals = new LinkedHashMap<>();
|
||||||
|
|
||||||
private long holdSignalsUntilElapsedMs;
|
private long holdSignalsUntilElapsedMs;
|
||||||
@@ -58,11 +63,21 @@ final class SnapshotRenderer {
|
|||||||
ArrayList<SnapshotPlacement> rawPlacements(
|
ArrayList<SnapshotPlacement> rawPlacements(
|
||||||
View root,
|
View root,
|
||||||
ArrayList<SnapshotSource> sources
|
ArrayList<SnapshotSource> sources
|
||||||
|
) {
|
||||||
|
return rawPlacements(root, sources, sortPlacementsByX);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<SnapshotPlacement> rawPlacements(
|
||||||
|
View root,
|
||||||
|
ArrayList<SnapshotSource> sources,
|
||||||
|
boolean sortByX
|
||||||
) {
|
) {
|
||||||
ArrayList<SnapshotPlacement> placements = new ArrayList<>();
|
ArrayList<SnapshotPlacement> placements = new ArrayList<>();
|
||||||
int order = 0;
|
int order = 0;
|
||||||
for (SnapshotSource source : sources) {
|
for (SnapshotSource source : sources) {
|
||||||
Bounds bounds = visualBoundsRelativeTo(root, source.view());
|
Bounds bounds = source.boundsOverride() != null
|
||||||
|
? source.boundsOverride()
|
||||||
|
: visualBoundsRelativeTo(root, source.view());
|
||||||
if (bounds != null && bounds.width > 0 && bounds.height > 0) {
|
if (bounds != null && bounds.width > 0 && bounds.height > 0) {
|
||||||
if (source.mode() == SnapshotMode.NOTIFICATION_DRAWABLE) {
|
if (source.mode() == SnapshotMode.NOTIFICATION_DRAWABLE) {
|
||||||
bounds = notificationDrawableBounds(bounds);
|
bounds = notificationDrawableBounds(bounds);
|
||||||
@@ -112,7 +127,7 @@ final class SnapshotRenderer {
|
|||||||
}
|
}
|
||||||
order++;
|
order++;
|
||||||
}
|
}
|
||||||
if (sortPlacementsByX) {
|
if (sortByX) {
|
||||||
placements.sort(Comparator.comparingInt(placement -> placement.bounds().left));
|
placements.sort(Comparator.comparingInt(placement -> placement.bounds().left));
|
||||||
}
|
}
|
||||||
return placements;
|
return placements;
|
||||||
@@ -176,11 +191,14 @@ final class SnapshotRenderer {
|
|||||||
|| !desiredState.equals(statesByProxy.get(proxy));
|
|| !desiredState.equals(statesByProxy.get(proxy));
|
||||||
if (bitmapChanged) {
|
if (bitmapChanged) {
|
||||||
if (placement.overflowDot()) {
|
if (placement.overflowDot()) {
|
||||||
drawOverflowDot(bitmap, placement.overflowDotColor());
|
drawOverflowDot(bitmap, placement.overflowDotColor(), placement.sourceOffsetX());
|
||||||
} else if (placement.heldSignal() != null) {
|
} else if (placement.heldSignal() != null) {
|
||||||
drawHeldSignal(placement.heldSignal(), bitmap);
|
drawHeldSignal(placement.heldSignal(), bitmap);
|
||||||
|
} else if (placement.source() != null
|
||||||
|
&& placement.source().mode() == SnapshotMode.APP_ICON) {
|
||||||
|
drawAppIcon(host.getContext(), placement.source(), bitmap);
|
||||||
} else if (placement.source() != null) {
|
} else if (placement.source() != null) {
|
||||||
drawSnapshot(placement.source(), bitmap, placement.sourceOffsetX());
|
drawSnapshot(placement, bitmap);
|
||||||
if (placement.signal()) {
|
if (placement.signal()) {
|
||||||
saveHeldSignal(key, bounds, bitmap);
|
saveHeldSignal(key, bounds, bitmap);
|
||||||
}
|
}
|
||||||
@@ -265,7 +283,9 @@ final class SnapshotRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldTrimContent(SnapshotSource source) {
|
private boolean shouldTrimContent(SnapshotSource source) {
|
||||||
return trimViewContentForCollision && source != null && source.mode() == SnapshotMode.VIEW;
|
return trimViewContentForCollision
|
||||||
|
&& source != null
|
||||||
|
&& (source.mode() == SnapshotMode.VIEW || source.mode() == SnapshotMode.STATUS_CHIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bounds bitmapContentBounds(Bitmap bitmap) {
|
private Bounds bitmapContentBounds(Bitmap bitmap) {
|
||||||
@@ -351,6 +371,9 @@ final class SnapshotRenderer {
|
|||||||
if (keyHint != null && !keyHint.isEmpty()) {
|
if (keyHint != null && !keyHint.isEmpty()) {
|
||||||
return keyHint;
|
return keyHint;
|
||||||
}
|
}
|
||||||
|
if (view == null) {
|
||||||
|
return source.mode().name().toLowerCase(java.util.Locale.ROOT) + "#" + order;
|
||||||
|
}
|
||||||
String slot = reflectString(view, "getSlot", "mSlot", "slot");
|
String slot = reflectString(view, "getSlot", "mSlot", "slot");
|
||||||
if (!slot.isEmpty()) {
|
if (!slot.isEmpty()) {
|
||||||
return slot;
|
return slot;
|
||||||
@@ -363,6 +386,9 @@ final class SnapshotRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String signalKind(View view, String key) {
|
private String signalKind(View view, String key) {
|
||||||
|
if (view == null || key == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
String lowerKey = key.toLowerCase(java.util.Locale.ROOT);
|
String lowerKey = key.toLowerCase(java.util.Locale.ROOT);
|
||||||
if (lowerKey.contains("wifi")) {
|
if (lowerKey.contains("wifi")) {
|
||||||
return "wifi";
|
return "wifi";
|
||||||
@@ -475,24 +501,60 @@ final class SnapshotRenderer {
|
|||||||
Bounds bounds = placement.bounds();
|
Bounds bounds = placement.bounds();
|
||||||
return new SnapshotRenderState(
|
return new SnapshotRenderState(
|
||||||
placement.key(),
|
placement.key(),
|
||||||
bounds.left,
|
|
||||||
bounds.top,
|
|
||||||
bounds.width,
|
bounds.width,
|
||||||
bounds.height,
|
bounds.height,
|
||||||
placement.signal(),
|
placement.signal(),
|
||||||
placement.overflowDot(),
|
placement.overflowDot(),
|
||||||
placement.overflowDotColor(),
|
placement.overflowDotColor(),
|
||||||
placement.sourceOffsetX(),
|
placement.sourceOffsetX(),
|
||||||
|
boundsSignature(placement.sourceRenderBounds()),
|
||||||
placement.heldSignal() != null ? placement.heldSignal().key : "",
|
placement.heldSignal() != null ? placement.heldSignal().key : "",
|
||||||
placement.heldSignal() != null ? System.identityHashCode(placement.heldSignal().bitmap) : 0,
|
placement.heldSignal() != null ? System.identityHashCode(placement.heldSignal().bitmap) : 0,
|
||||||
placement.source() != null ? placement.source().mode() : null,
|
placement.source() != null ? placement.source().mode() : null,
|
||||||
placement.source() != null ? sourceTreeSignature(placement.source().view()) : 0);
|
placement.source() != null ? sourceSignature(placement.source()) : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int sourceSignature(SnapshotSource source) {
|
||||||
|
if (source == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + sourceTreeSignature(source.view());
|
||||||
|
result = 31 * result + boundsSignature(source.boundsOverride());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int boundsSignature(Bounds bounds) {
|
||||||
|
if (bounds == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + bounds.left;
|
||||||
|
result = 31 * result + bounds.top;
|
||||||
|
result = 31 * result + bounds.width;
|
||||||
|
result = 31 * result + bounds.height;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStatusBarIconView(View view) {
|
||||||
|
return view != null && view.getClass().getName().contains("StatusBarIconView");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sourceTreeSignature(View view) {
|
private int sourceTreeSignature(View view) {
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int stamp = sourceSignatureStamp(view);
|
||||||
|
SourceSignatureCache cached = sourceSignaturesByView.get(view);
|
||||||
|
if (cached != null && cached.stamp == stamp) {
|
||||||
|
return cached.signature;
|
||||||
|
}
|
||||||
|
int signature = computeSourceTreeSignature(view);
|
||||||
|
sourceSignaturesByView.put(view, new SourceSignatureCache(stamp, signature));
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeSourceTreeSignature(View view) {
|
||||||
int result = 17;
|
int result = 17;
|
||||||
result = 31 * result + System.identityHashCode(view);
|
result = 31 * result + System.identityHashCode(view);
|
||||||
result = 31 * result + view.getVisibility();
|
result = 31 * result + view.getVisibility();
|
||||||
@@ -523,6 +585,53 @@ final class SnapshotRenderer {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int sourceSignatureStamp(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + System.identityHashCode(view);
|
||||||
|
result = 31 * result + view.getVisibility();
|
||||||
|
result = 31 * result + Float.floatToIntBits(view.getAlpha());
|
||||||
|
result = 31 * result + view.getWidth();
|
||||||
|
result = 31 * result + view.getHeight();
|
||||||
|
result = 31 * result + view.getScrollX();
|
||||||
|
result = 31 * result + view.getScrollY();
|
||||||
|
result = 31 * result + java.util.Arrays.hashCode(view.getDrawableState());
|
||||||
|
result = 31 * result + SnapshotAppearanceSignature.view(view);
|
||||||
|
if (view instanceof TextView textView) {
|
||||||
|
CharSequence text = textView.getText();
|
||||||
|
result = 31 * result + (text != null ? text.toString().hashCode() : 0);
|
||||||
|
result = 31 * result + textView.getCurrentTextColor();
|
||||||
|
result = 31 * result + Float.floatToIntBits(textView.getTextSize());
|
||||||
|
}
|
||||||
|
if (view instanceof ImageView imageView) {
|
||||||
|
Drawable drawable = imageView.getDrawable();
|
||||||
|
result = 31 * result + System.identityHashCode(drawable);
|
||||||
|
if (drawable != null) {
|
||||||
|
result = 31 * result + drawable.getLevel();
|
||||||
|
result = 31 * result + drawable.getAlpha();
|
||||||
|
result = 31 * result + java.util.Arrays.hashCode(drawable.getState());
|
||||||
|
}
|
||||||
|
result = 31 * result + (imageView.getImageTintList() != null
|
||||||
|
? imageView.getImageTintList().hashCode()
|
||||||
|
: 0);
|
||||||
|
result = 31 * result + (imageView.getColorFilter() != null
|
||||||
|
? System.identityHashCode(imageView.getColorFilter())
|
||||||
|
: 0);
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
result = 31 * result + group.getChildCount();
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
result = 31 * result + sourceSignatureStamp(group.getChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private record SourceSignatureCache(int stamp, int signature) {
|
||||||
|
}
|
||||||
|
|
||||||
private int drawableSignature(Drawable drawable) {
|
private int drawableSignature(Drawable drawable) {
|
||||||
if (drawable == null) {
|
if (drawable == null) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -548,9 +657,22 @@ final class SnapshotRenderer {
|
|||||||
canvas.translate(-offsetX, 0);
|
canvas.translate(-offsetX, 0);
|
||||||
}
|
}
|
||||||
View sourceView = source.view();
|
View sourceView = source.view();
|
||||||
|
if (sourceView == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int oldVisibility = sourceView.getVisibility();
|
int oldVisibility = sourceView.getVisibility();
|
||||||
float oldAlpha = sourceView.getAlpha();
|
float oldAlpha = sourceView.getAlpha();
|
||||||
try {
|
try {
|
||||||
|
// StatusBarIconView may be mid-transition while its drawable is valid.
|
||||||
|
if (source.mode() == SnapshotMode.VIEW
|
||||||
|
&& isStatusBarIconView(sourceView)
|
||||||
|
&& drawNotificationDrawable(
|
||||||
|
sourceView,
|
||||||
|
canvas,
|
||||||
|
bitmap.getWidth(),
|
||||||
|
bitmap.getHeight())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (source.mode() == SnapshotMode.NOTIFICATION_DRAWABLE
|
if (source.mode() == SnapshotMode.NOTIFICATION_DRAWABLE
|
||||||
&& drawNotificationDrawable(
|
&& drawNotificationDrawable(
|
||||||
sourceView,
|
sourceView,
|
||||||
@@ -561,13 +683,287 @@ final class SnapshotRenderer {
|
|||||||
}
|
}
|
||||||
sourceView.setVisibility(View.VISIBLE);
|
sourceView.setVisibility(View.VISIBLE);
|
||||||
sourceView.setAlpha(1f);
|
sourceView.setAlpha(1f);
|
||||||
|
if (source.mode() == SnapshotMode.STATUS_CHIP) {
|
||||||
|
drawTemporarilySizedView(sourceView, canvas, bitmap.getWidth(), bitmap.getHeight());
|
||||||
|
} else {
|
||||||
sourceView.draw(canvas);
|
sourceView.draw(canvas);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
sourceView.setAlpha(oldAlpha);
|
sourceView.setAlpha(oldAlpha);
|
||||||
sourceView.setVisibility(oldVisibility);
|
sourceView.setVisibility(oldVisibility);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void drawSnapshot(SnapshotPlacement placement, Bitmap bitmap) {
|
||||||
|
SnapshotSource source = placement.source();
|
||||||
|
if (source == null) {
|
||||||
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bounds sourceRenderBounds = placement.sourceRenderBounds();
|
||||||
|
if ((source.mode() != SnapshotMode.STATUS_CHIP && source.mode() != SnapshotMode.VIEW)
|
||||||
|
|| sourceRenderBounds == null
|
||||||
|
|| sourceRenderBounds.width <= 0
|
||||||
|
|| sourceRenderBounds.height <= 0
|
||||||
|
|| bitmap.getWidth() <= 0
|
||||||
|
|| bitmap.getHeight() <= 0) {
|
||||||
|
drawSnapshot(source, bitmap, placement.sourceOffsetX());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sourceRenderBounds = effectiveSourceRenderBounds(
|
||||||
|
placement,
|
||||||
|
sourceRenderBounds,
|
||||||
|
bitmap.getWidth(),
|
||||||
|
bitmap.getHeight());
|
||||||
|
if (sourceRenderBounds.width == bitmap.getWidth()
|
||||||
|
&& sourceRenderBounds.height == bitmap.getHeight()) {
|
||||||
|
drawSnapshot(source, bitmap, placement.sourceOffsetX());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Bitmap sourceBitmap = Bitmap.createBitmap(
|
||||||
|
sourceRenderBounds.width,
|
||||||
|
sourceRenderBounds.height,
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
try {
|
||||||
|
drawSnapshot(source, sourceBitmap, 0);
|
||||||
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG
|
||||||
|
| Paint.FILTER_BITMAP_FLAG
|
||||||
|
| Paint.DITHER_FLAG);
|
||||||
|
float scale = (float) bitmap.getHeight() / sourceRenderBounds.height;
|
||||||
|
int scaledWidth = Math.max(1, Math.round(sourceRenderBounds.width * scale));
|
||||||
|
canvas.translate(-placement.sourceOffsetX(), 0);
|
||||||
|
canvas.drawBitmap(
|
||||||
|
sourceBitmap,
|
||||||
|
null,
|
||||||
|
new Rect(0, 0, scaledWidth, bitmap.getHeight()),
|
||||||
|
paint);
|
||||||
|
} finally {
|
||||||
|
sourceBitmap.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds effectiveSourceRenderBounds(
|
||||||
|
SnapshotPlacement placement,
|
||||||
|
Bounds requestedBounds,
|
||||||
|
int outputWidth,
|
||||||
|
int outputHeight
|
||||||
|
) {
|
||||||
|
if (placement == null
|
||||||
|
|| requestedBounds == null
|
||||||
|
|| placement.source() == null
|
||||||
|
|| placement.source().mode() != SnapshotMode.STATUS_CHIP
|
||||||
|
|| placement.contentBounds() == null
|
||||||
|
|| placement.contentBounds().width <= 0
|
||||||
|
|| outputWidth <= 0
|
||||||
|
|| outputHeight <= 0
|
||||||
|
|| requestedBounds.width <= 0
|
||||||
|
|| requestedBounds.height <= 0) {
|
||||||
|
return requestedBounds;
|
||||||
|
}
|
||||||
|
float scale = (float) outputHeight / requestedBounds.height;
|
||||||
|
if (scale <= 0f) {
|
||||||
|
return requestedBounds;
|
||||||
|
}
|
||||||
|
int targetContentWidth = Math.max(1, Math.round(placement.contentBounds().width / scale));
|
||||||
|
int maxWidth = Math.max(1, Math.round(outputWidth / scale));
|
||||||
|
int width = Math.max(1, Math.min(requestedBounds.width, maxWidth));
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
Bounds content = sourceContentBoundsAtWidth(placement.source(), width, requestedBounds.height);
|
||||||
|
if (content == null || content.width <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int delta = targetContentWidth - content.width;
|
||||||
|
if (Math.abs(delta) <= 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int nextWidth = Math.max(1, Math.min(maxWidth, width + delta));
|
||||||
|
if (nextWidth == width) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
width = nextWidth;
|
||||||
|
}
|
||||||
|
return new Bounds(
|
||||||
|
requestedBounds.left,
|
||||||
|
requestedBounds.top,
|
||||||
|
width,
|
||||||
|
requestedBounds.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds sourceContentBoundsAtWidth(SnapshotSource source, int width, int height) {
|
||||||
|
if (source == null || width <= 0 || height <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
|
||||||
|
try {
|
||||||
|
drawSnapshot(source, bitmap, 0);
|
||||||
|
return bitmapContentBounds(bitmap);
|
||||||
|
} finally {
|
||||||
|
bitmap.recycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawTemporarilySizedView(View view, Canvas canvas, int width, int height) {
|
||||||
|
int oldLeft = view.getLeft();
|
||||||
|
int oldTop = view.getTop();
|
||||||
|
int oldRight = view.getRight();
|
||||||
|
int oldBottom = view.getBottom();
|
||||||
|
int oldMeasuredWidth = view.getMeasuredWidth();
|
||||||
|
int oldMeasuredHeight = view.getMeasuredHeight();
|
||||||
|
ViewFrameState frameState = captureFrameState(view);
|
||||||
|
IdentityHashMap<TextView, Integer> oldMaxWidths = clearTextMaxWidths(view);
|
||||||
|
try {
|
||||||
|
int widthSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, width), View.MeasureSpec.EXACTLY);
|
||||||
|
int heightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(1, height), View.MeasureSpec.EXACTLY);
|
||||||
|
view.measure(widthSpec, heightSpec);
|
||||||
|
view.layout(oldLeft, oldTop, oldLeft + Math.max(1, width), oldTop + Math.max(1, height));
|
||||||
|
clampDescendantsToParent(view);
|
||||||
|
view.draw(canvas);
|
||||||
|
} finally {
|
||||||
|
restoreTextMaxWidths(oldMaxWidths);
|
||||||
|
restoreFrameState(frameState);
|
||||||
|
if (oldMeasuredWidth > 0 && oldMeasuredHeight > 0) {
|
||||||
|
view.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(oldMeasuredWidth, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(oldMeasuredHeight, View.MeasureSpec.EXACTLY));
|
||||||
|
}
|
||||||
|
view.layout(oldLeft, oldTop, oldRight, oldBottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clampDescendantsToParent(View view) {
|
||||||
|
if (!(view instanceof ViewGroup group)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int parentRight = Math.max(0, group.getWidth() - group.getPaddingRight());
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (child == null || child.getVisibility() == View.GONE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int availableWidth = Math.max(0, parentRight - child.getLeft());
|
||||||
|
int currentWidth = child.getWidth() > 0 ? child.getWidth() : child.getMeasuredWidth();
|
||||||
|
int currentHeight = child.getHeight() > 0 ? child.getHeight() : child.getMeasuredHeight();
|
||||||
|
if (availableWidth > 0 && currentWidth > availableWidth && currentHeight > 0) {
|
||||||
|
child.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(currentHeight, View.MeasureSpec.EXACTLY));
|
||||||
|
child.layout(
|
||||||
|
child.getLeft(),
|
||||||
|
child.getTop(),
|
||||||
|
child.getLeft() + availableWidth,
|
||||||
|
child.getTop() + currentHeight);
|
||||||
|
}
|
||||||
|
clampDescendantsToParent(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ViewFrameState captureFrameState(View root) {
|
||||||
|
ViewFrameState state = new ViewFrameState();
|
||||||
|
captureFrameState(root, state);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void captureFrameState(View view, ViewFrameState state) {
|
||||||
|
if (view == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.views.add(view);
|
||||||
|
state.frames.put(view, new ViewFrame(
|
||||||
|
view.getLeft(),
|
||||||
|
view.getTop(),
|
||||||
|
view.getRight(),
|
||||||
|
view.getBottom(),
|
||||||
|
view.getMeasuredWidth(),
|
||||||
|
view.getMeasuredHeight()));
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
captureFrameState(group.getChildAt(i), state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreFrameState(ViewFrameState state) {
|
||||||
|
if (state == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = state.views.size() - 1; i >= 0; i--) {
|
||||||
|
View view = state.views.get(i);
|
||||||
|
ViewFrame frame = state.frames.get(view);
|
||||||
|
if (view == null || frame == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (frame.measuredWidth > 0 && frame.measuredHeight > 0) {
|
||||||
|
view.measure(
|
||||||
|
View.MeasureSpec.makeMeasureSpec(frame.measuredWidth, View.MeasureSpec.EXACTLY),
|
||||||
|
View.MeasureSpec.makeMeasureSpec(frame.measuredHeight, View.MeasureSpec.EXACTLY));
|
||||||
|
}
|
||||||
|
view.layout(frame.left, frame.top, frame.right, frame.bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ViewFrameState {
|
||||||
|
final ArrayList<View> views = new ArrayList<>();
|
||||||
|
final IdentityHashMap<View, ViewFrame> frames = new IdentityHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private record ViewFrame(
|
||||||
|
int left,
|
||||||
|
int top,
|
||||||
|
int right,
|
||||||
|
int bottom,
|
||||||
|
int measuredWidth,
|
||||||
|
int measuredHeight
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdentityHashMap<TextView, Integer> clearTextMaxWidths(View view) {
|
||||||
|
IdentityHashMap<TextView, Integer> oldMaxWidths = new IdentityHashMap<>();
|
||||||
|
collectTextMaxWidths(view, oldMaxWidths);
|
||||||
|
for (Map.Entry<TextView, Integer> entry : oldMaxWidths.entrySet()) {
|
||||||
|
entry.getKey().setMaxWidth(Integer.MAX_VALUE);
|
||||||
|
}
|
||||||
|
return oldMaxWidths;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectTextMaxWidths(View view, IdentityHashMap<TextView, Integer> out) {
|
||||||
|
if (view instanceof TextView textView) {
|
||||||
|
out.put(textView, textView.getMaxWidth());
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
collectTextMaxWidths(group.getChildAt(i), out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreTextMaxWidths(IdentityHashMap<TextView, Integer> oldMaxWidths) {
|
||||||
|
for (Map.Entry<TextView, Integer> entry : oldMaxWidths.entrySet()) {
|
||||||
|
entry.getKey().setMaxWidth(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawAppIcon(Context context, SnapshotSource source, Bitmap bitmap) {
|
||||||
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
|
if (context == null || source == null || source.keyHint() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String packageName = source.keyHint();
|
||||||
|
int suffixIndex = packageName.indexOf('@');
|
||||||
|
if (suffixIndex > 0) {
|
||||||
|
packageName = packageName.substring(0, suffixIndex);
|
||||||
|
}
|
||||||
|
Drawable drawable = context.getPackageManager().getApplicationIcon(packageName);
|
||||||
|
Canvas canvas = new Canvas(bitmap);
|
||||||
|
drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||||
|
drawable.draw(canvas);
|
||||||
|
} catch (PackageManager.NameNotFoundException ignored) {
|
||||||
|
// Unknown packages fail closed: keep the icon transparent rather than guessing.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void drawHeldSignal(HeldSignal heldSignal, Bitmap bitmap) {
|
private void drawHeldSignal(HeldSignal heldSignal, Bitmap bitmap) {
|
||||||
bitmap.eraseColor(Color.TRANSPARENT);
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
if (heldSignal.bitmap == null || heldSignal.bitmap.isRecycled()) {
|
if (heldSignal.bitmap == null || heldSignal.bitmap.isRecycled()) {
|
||||||
@@ -579,16 +975,18 @@ final class SnapshotRenderer {
|
|||||||
canvas.drawBitmap(heldSignal.bitmap, src, dst, null);
|
canvas.drawBitmap(heldSignal.bitmap, src, dst, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawOverflowDot(Bitmap bitmap, int color) {
|
private void drawOverflowDot(Bitmap bitmap, int color, int centerOffsetX) {
|
||||||
bitmap.eraseColor(Color.TRANSPARENT);
|
bitmap.eraseColor(Color.TRANSPARENT);
|
||||||
if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
|
if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float radius = Math.max(1f, Math.min(bitmap.getWidth() / 2f, bitmap.getHeight() * 0.16f));
|
float radius = Math.max(1f, Math.min(bitmap.getWidth() / 2f, bitmap.getHeight() * 0.125f));
|
||||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||||
paint.setColor(color);
|
paint.setColor(color);
|
||||||
Canvas canvas = new Canvas(bitmap);
|
Canvas canvas = new Canvas(bitmap);
|
||||||
canvas.drawCircle(bitmap.getWidth() / 2f, bitmap.getHeight() / 2f, radius, paint);
|
float centerX = bitmap.getWidth() / 2f + centerOffsetX;
|
||||||
|
centerX = Math.max(radius, Math.min(bitmap.getWidth() - radius, centerX));
|
||||||
|
canvas.drawCircle(centerX, bitmap.getHeight() / 2f, radius, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean drawNotificationDrawable(View source, Canvas canvas, int width, int height) {
|
private boolean drawNotificationDrawable(View source, Canvas canvas, int width, int height) {
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public final class StatusIconSlotVisibilityStore {
|
||||||
|
private static final Object LOCK = new Object();
|
||||||
|
private static ArrayList<String> activeSlots = new ArrayList<>();
|
||||||
|
|
||||||
|
private StatusIconSlotVisibilityStore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setActiveSlots(ArrayList<String> slots) {
|
||||||
|
ArrayList<String> normalized = normalize(slots);
|
||||||
|
synchronized (LOCK) {
|
||||||
|
if (activeSlots.equals(normalized)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
activeSlots = normalized;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArrayList<String> activeSlotList() {
|
||||||
|
synchronized (LOCK) {
|
||||||
|
return new ArrayList<>(activeSlots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ArrayList<String> normalize(ArrayList<String> slots) {
|
||||||
|
ArrayList<String> normalized = new ArrayList<>();
|
||||||
|
if (slots == null) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
for (String slot : slots) {
|
||||||
|
if (slot == null || slot.isEmpty() || normalized.contains(slot)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
normalized.add(slot);
|
||||||
|
}
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
}
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
|
||||||
|
import se.ajpanton.statusbartweak.runtime.layoutsolver.StatusBarLayoutSolver.Bounds;
|
||||||
|
import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
|
||||||
|
|
||||||
|
final class StatusbarHeightSource {
|
||||||
|
private StatusbarHeightSource() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bounds bounds(View root, SceneKey scene, RootAnchors anchors) {
|
||||||
|
if (root == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (scene != null && scene.isAod()) {
|
||||||
|
Bounds aodBounds = firstBoundsForIds(root,
|
||||||
|
"common_battery_statusbar_container",
|
||||||
|
"keyguard_status_bar_container",
|
||||||
|
"keyguard_header");
|
||||||
|
if (isUsable(root, aodBounds)) {
|
||||||
|
return aodBounds;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Bounds anchorBounds = ViewGeometry.boundsRelativeTo(root, anchors != null ? anchors.statusRoot : null);
|
||||||
|
if (isUsable(root, anchorBounds)) {
|
||||||
|
return anchorBounds;
|
||||||
|
}
|
||||||
|
Bounds scannedBounds = firstBoundsForIds(root,
|
||||||
|
"system_icon_area",
|
||||||
|
"status_bar_contents",
|
||||||
|
"status_bar");
|
||||||
|
if (isUsable(root, scannedBounds)) {
|
||||||
|
return scannedBounds;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int height(View root, SceneKey scene, RootAnchors anchors, Bounds fallbackBounds) {
|
||||||
|
Bounds bounds = bounds(root, scene, anchors);
|
||||||
|
if (isUsable(root, bounds)) {
|
||||||
|
return bounds.top + bounds.height;
|
||||||
|
}
|
||||||
|
if (isUsable(root, fallbackBounds)) {
|
||||||
|
return fallbackBounds.top + fallbackBounds.height;
|
||||||
|
}
|
||||||
|
return Math.max(1, root != null ? root.getHeight() : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Bounds firstBoundsForIds(View root, String... idNames) {
|
||||||
|
if (!(root instanceof ViewGroup rootGroup) || idNames == null || idNames.length == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (String candidateId : idNames) {
|
||||||
|
ArrayDeque<View> queue = new ArrayDeque<>();
|
||||||
|
queue.add(rootGroup);
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
View view = queue.removeFirst();
|
||||||
|
if (candidateId.equals(resolveIdName(view))) {
|
||||||
|
Bounds bounds = ViewGeometry.boundsRelativeTo(root, view);
|
||||||
|
if (isUsable(root, bounds)) {
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (child != null) {
|
||||||
|
queue.addLast(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isUsable(View root, Bounds bounds) {
|
||||||
|
if (root == null || bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int right = bounds.left + bounds.width;
|
||||||
|
int bottom = bounds.top + bounds.height;
|
||||||
|
return bounds.left >= 0
|
||||||
|
&& bounds.top >= 0
|
||||||
|
&& right <= root.getWidth()
|
||||||
|
&& bottom <= root.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String resolveIdName(View view) {
|
||||||
|
if (view == null || view.getId() == View.NO_ID) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return view.getResources().getResourceEntryName(view.getId());
|
||||||
|
} catch (Resources.NotFoundException ignored) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
final class StatusbarHeightStore {
|
||||||
|
private static final int MAX_ENTRIES = 4;
|
||||||
|
private static final Map<Integer, Integer> HEIGHT_BY_ROOT_WIDTH = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
private StatusbarHeightStore() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void put(View root, int height) {
|
||||||
|
if (root == null || root.getWidth() <= 0 || height <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
HEIGHT_BY_ROOT_WIDTH.put(root.getWidth(), height);
|
||||||
|
while (HEIGHT_BY_ROOT_WIDTH.size() > MAX_ENTRIES) {
|
||||||
|
Integer oldest = HEIGHT_BY_ROOT_WIDTH.keySet().iterator().next();
|
||||||
|
HEIGHT_BY_ROOT_WIDTH.remove(oldest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get(View root) {
|
||||||
|
if (root == null || root.getWidth() <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Integer height = HEIGHT_BY_ROOT_WIDTH.get(root.getWidth());
|
||||||
|
return height != null && height > 0 ? height : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
+155
-53
@@ -1,6 +1,8 @@
|
|||||||
package se.ajpanton.statusbartweak.runtime.render;
|
package se.ajpanton.statusbartweak.runtime.render;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -9,15 +11,13 @@ import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
|||||||
|
|
||||||
final class UnlockedChipPlacementController {
|
final class UnlockedChipPlacementController {
|
||||||
private final SnapshotRenderer renderer;
|
private final SnapshotRenderer renderer;
|
||||||
private final UnlockedVerticalOffsetScaler offsetScaler;
|
|
||||||
private ChipHoldState heldPlacements;
|
private ChipHoldState heldPlacements;
|
||||||
private Bounds lastCollisionBounds;
|
private Bounds lastCollisionBounds;
|
||||||
private int lastRootWidth;
|
private int lastRootWidth;
|
||||||
private int lastRootHeight;
|
private int lastRootHeight;
|
||||||
|
|
||||||
UnlockedChipPlacementController(SnapshotRenderer renderer, UnlockedVerticalOffsetScaler offsetScaler) {
|
UnlockedChipPlacementController(SnapshotRenderer renderer) {
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.offsetScaler = offsetScaler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
@@ -33,31 +33,169 @@ final class UnlockedChipPlacementController {
|
|||||||
ArrayList<SnapshotSource> metricSources,
|
ArrayList<SnapshotSource> metricSources,
|
||||||
SbtSettings settings
|
SbtSettings settings
|
||||||
) {
|
) {
|
||||||
ArrayList<SnapshotPlacement> rawPlacements = renderer.rawPlacements(root, visibleSources);
|
ArrayList<SnapshotPlacement> rawPlacements = renderer.rawPlacements(
|
||||||
|
root,
|
||||||
|
withNaturalChipBounds(root, visibleSources));
|
||||||
|
rawPlacements = withVisualChipCollision(rawPlacements);
|
||||||
if (!rawPlacements.isEmpty()) {
|
if (!rawPlacements.isEmpty()) {
|
||||||
rememberMetrics(root, rawPlacements);
|
rememberMetrics(root, rawPlacements);
|
||||||
ArrayList<SnapshotPlacement> placements = offsetPlacements(
|
|
||||||
rawPlacements,
|
|
||||||
offsetScaler.chip(
|
|
||||||
settings.layoutChipVerticalOffsetPx,
|
|
||||||
representativeChipHeight(rawPlacements)));
|
|
||||||
heldPlacements = new ChipHoldState(
|
heldPlacements = new ChipHoldState(
|
||||||
copyAsHeldPlacements(placements),
|
copyAsHeldPlacements(rawPlacements),
|
||||||
root.getWidth(),
|
root.getWidth(),
|
||||||
root.getHeight(),
|
root.getHeight(),
|
||||||
0);
|
0);
|
||||||
return placements;
|
return rawPlacements;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayList<SnapshotPlacement> placements = isAnyChipHidingEnabled(settings)
|
ArrayList<SnapshotPlacement> placements = isAnyChipHidingEnabled(settings)
|
||||||
? new ArrayList<>()
|
? new ArrayList<>()
|
||||||
: heldPlacements(root);
|
: heldPlacements(root);
|
||||||
if (placements.isEmpty()) {
|
if (placements.isEmpty()) {
|
||||||
placements = emptyPlacement(root, metricSources, settings);
|
placements = emptyPlacement(root, metricSources);
|
||||||
}
|
}
|
||||||
return placements;
|
return placements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<SnapshotPlacement> withVisualChipCollision(ArrayList<SnapshotPlacement> placements) {
|
||||||
|
if (placements == null || placements.isEmpty()) {
|
||||||
|
return placements;
|
||||||
|
}
|
||||||
|
ArrayList<SnapshotPlacement> result = null;
|
||||||
|
for (int i = 0; i < placements.size(); i++) {
|
||||||
|
SnapshotPlacement placement = placements.get(i);
|
||||||
|
if (placement == null
|
||||||
|
|| placement.source == null
|
||||||
|
|| placement.source.mode() != SnapshotMode.STATUS_CHIP
|
||||||
|
|| placement.contentBounds == null
|
||||||
|
|| placement.bounds == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds visualCollision = new Bounds(
|
||||||
|
placement.contentBounds.left,
|
||||||
|
placement.contentBounds.top,
|
||||||
|
placement.contentBounds.width,
|
||||||
|
placement.contentBounds.height);
|
||||||
|
if (visualCollision.equals(placement.contentBounds)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (result == null) {
|
||||||
|
result = new ArrayList<>(placements);
|
||||||
|
}
|
||||||
|
result.set(i, new SnapshotPlacement(
|
||||||
|
placement.source,
|
||||||
|
placement.bounds,
|
||||||
|
placement.key,
|
||||||
|
placement.signal,
|
||||||
|
placement.overflowDot,
|
||||||
|
placement.overflowDotColor,
|
||||||
|
placement.heldSignal,
|
||||||
|
visualCollision,
|
||||||
|
placement.sourceOffsetX));
|
||||||
|
}
|
||||||
|
return result != null ? result : placements;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<SnapshotSource> withNaturalChipBounds(
|
||||||
|
View root,
|
||||||
|
ArrayList<SnapshotSource> sources
|
||||||
|
) {
|
||||||
|
if (root == null || sources == null || sources.isEmpty()) {
|
||||||
|
return sources;
|
||||||
|
}
|
||||||
|
ArrayList<SnapshotSource> result = null;
|
||||||
|
for (int i = 0; i < sources.size(); i++) {
|
||||||
|
SnapshotSource source = sources.get(i);
|
||||||
|
SnapshotSource normalized = withNaturalChipBounds(root, source);
|
||||||
|
if (normalized != source && result == null) {
|
||||||
|
result = new ArrayList<>(sources);
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
result.set(i, normalized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result != null ? result : sources;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SnapshotSource withNaturalChipBounds(View root, SnapshotSource source) {
|
||||||
|
if (source == null || source.mode() != SnapshotMode.STATUS_CHIP) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
Bounds bounds = source.boundsOverride() != null
|
||||||
|
? source.boundsOverride()
|
||||||
|
: ViewGeometry.boundsRelativeTo(root, source.view());
|
||||||
|
if (bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
int naturalWidth = naturalChipWidth(source.view(), bounds.width, root.getWidth());
|
||||||
|
if (naturalWidth <= bounds.width) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
return new SnapshotSource(
|
||||||
|
source.view(),
|
||||||
|
source.mode(),
|
||||||
|
source.keyHint(),
|
||||||
|
new Bounds(bounds.left, bounds.top, naturalWidth, bounds.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int naturalChipWidth(View view, int currentWidth, int maxWidth) {
|
||||||
|
if (view == null) {
|
||||||
|
return currentWidth;
|
||||||
|
}
|
||||||
|
int width = naturalContentWidth(view);
|
||||||
|
if (maxWidth > 0) {
|
||||||
|
width = Math.min(width, maxWidth);
|
||||||
|
}
|
||||||
|
return Math.max(currentWidth, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int naturalContentWidth(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int width = measuredWidth(view);
|
||||||
|
if (view instanceof TextView textView) {
|
||||||
|
width = Math.max(width, naturalTextWidth(textView));
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
int childRight = group.getPaddingLeft() + group.getPaddingRight();
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (child == null || child.getVisibility() == View.GONE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ViewGroup.LayoutParams lp = child.getLayoutParams();
|
||||||
|
int margins = 0;
|
||||||
|
if (lp instanceof ViewGroup.MarginLayoutParams marginParams) {
|
||||||
|
margins = marginParams.leftMargin + marginParams.rightMargin;
|
||||||
|
}
|
||||||
|
childRight = Math.max(
|
||||||
|
childRight,
|
||||||
|
child.getLeft() + margins + naturalContentWidth(child));
|
||||||
|
}
|
||||||
|
width = Math.max(width, childRight + group.getPaddingRight());
|
||||||
|
}
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int measuredWidth(View view) {
|
||||||
|
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
||||||
|
ViewGroup.LayoutParams lp = view.getLayoutParams();
|
||||||
|
if (lp != null && lp.width > 0) {
|
||||||
|
width = Math.max(width, lp.width);
|
||||||
|
}
|
||||||
|
return Math.max(0, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int naturalTextWidth(TextView textView) {
|
||||||
|
CharSequence text = textView.getText();
|
||||||
|
int textWidth = text != null && text.length() > 0
|
||||||
|
? (int) Math.ceil(textView.getPaint().measureText(text, 0, text.length()))
|
||||||
|
: 0;
|
||||||
|
return textWidth
|
||||||
|
+ textView.getCompoundPaddingLeft()
|
||||||
|
+ textView.getCompoundPaddingRight();
|
||||||
|
}
|
||||||
|
|
||||||
private ArrayList<SnapshotPlacement> heldPlacements(View root) {
|
private ArrayList<SnapshotPlacement> heldPlacements(View root) {
|
||||||
ChipHoldState state = heldPlacements;
|
ChipHoldState state = heldPlacements;
|
||||||
if (state == null || state.placements.isEmpty()) {
|
if (state == null || state.placements.isEmpty()) {
|
||||||
@@ -81,20 +219,16 @@ final class UnlockedChipPlacementController {
|
|||||||
|
|
||||||
private ArrayList<SnapshotPlacement> emptyPlacement(
|
private ArrayList<SnapshotPlacement> emptyPlacement(
|
||||||
View root,
|
View root,
|
||||||
ArrayList<SnapshotSource> sources,
|
ArrayList<SnapshotSource> sources
|
||||||
SbtSettings settings
|
|
||||||
) {
|
) {
|
||||||
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
||||||
Bounds bounds = emptyBounds(root, sources);
|
Bounds bounds = emptyBounds(root, sources);
|
||||||
if (bounds == null || bounds.height <= 0) {
|
if (bounds == null || bounds.height <= 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
int verticalOffset = offsetScaler.chip(
|
|
||||||
settings != null ? settings.layoutChipVerticalOffsetPx : 0,
|
|
||||||
bounds.height);
|
|
||||||
result.add(new SnapshotPlacement(
|
result.add(new SnapshotPlacement(
|
||||||
null,
|
null,
|
||||||
new Bounds(0, bounds.top - verticalOffset, 1, bounds.height),
|
new Bounds(0, bounds.top, 1, bounds.height),
|
||||||
SnapshotKeys.EMPTY_CHIP,
|
SnapshotKeys.EMPTY_CHIP,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -119,7 +253,9 @@ final class UnlockedChipPlacementController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (SnapshotSource source : sources) {
|
for (SnapshotSource source : sources) {
|
||||||
Bounds bounds = ViewGeometry.boundsRelativeTo(root, source.view());
|
Bounds bounds = source.boundsOverride() != null
|
||||||
|
? source.boundsOverride()
|
||||||
|
: ViewGeometry.boundsRelativeTo(root, source.view());
|
||||||
if (bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
if (bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -198,40 +334,6 @@ final class UnlockedChipPlacementController {
|
|||||||
return held;
|
return held;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList<SnapshotPlacement> offsetPlacements(ArrayList<SnapshotPlacement> placements, int verticalOffsetPx) {
|
|
||||||
if (placements == null || placements.isEmpty() || verticalOffsetPx == 0) {
|
|
||||||
return placements;
|
|
||||||
}
|
|
||||||
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
|
||||||
int dy = -verticalOffsetPx;
|
|
||||||
for (SnapshotPlacement placement : placements) {
|
|
||||||
Bounds bounds = placement.bounds;
|
|
||||||
result.add(new SnapshotPlacement(
|
|
||||||
placement.source,
|
|
||||||
new Bounds(bounds.left, bounds.top + dy, bounds.width, bounds.height),
|
|
||||||
placement.key,
|
|
||||||
placement.signal,
|
|
||||||
placement.overflowDot,
|
|
||||||
placement.overflowDotColor,
|
|
||||||
placement.heldSignal,
|
|
||||||
placement.contentBounds,
|
|
||||||
placement.sourceOffsetX));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int representativeChipHeight(ArrayList<SnapshotPlacement> placements) {
|
|
||||||
Bounds bounds = collisionUnion(placements);
|
|
||||||
return bounds != null ? Math.max(0, bounds.height) : representativeHeight(placements);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int representativeHeight(ArrayList<SnapshotPlacement> placements) {
|
|
||||||
if (placements == null || placements.isEmpty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return Math.max(0, placements.get(0).bounds.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
private record ChipHoldState(
|
private record ChipHoldState(
|
||||||
ArrayList<SnapshotPlacement> placements,
|
ArrayList<SnapshotPlacement> placements,
|
||||||
int rootWidth,
|
int rootWidth,
|
||||||
|
|||||||
+125
-18
@@ -5,10 +5,14 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
|
||||||
import se.ajpanton.statusbartweak.runtime.features.clock.ClockLayoutTextFactory;
|
import se.ajpanton.statusbartweak.runtime.features.clock.ClockLayoutTextFactory;
|
||||||
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.SceneKey;
|
import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
|
||||||
import se.ajpanton.statusbartweak.runtime.settings.RuntimeSettingsCache;
|
import se.ajpanton.statusbartweak.runtime.settings.RuntimeSettingsCache;
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||||
@@ -20,34 +24,44 @@ import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
|||||||
* into owned unlocked rows instead of copying each stock X position.
|
* into owned unlocked rows instead of copying each stock X position.
|
||||||
*/
|
*/
|
||||||
public final class UnlockedIconSnapshotRenderController {
|
public final class UnlockedIconSnapshotRenderController {
|
||||||
|
private final RuntimeContext runtimeContext;
|
||||||
private final SnapshotRenderer statusRenderer;
|
private final SnapshotRenderer statusRenderer;
|
||||||
private final SnapshotRenderer notificationRenderer;
|
private final SnapshotRenderer notificationRenderer;
|
||||||
private final SnapshotRenderer chipRenderer;
|
private final SnapshotRenderer chipRenderer;
|
||||||
private final ClockProxyRenderer clockRenderer = new ClockProxyRenderer();
|
private final ClockProxyRenderer clockRenderer = new ClockProxyRenderer();
|
||||||
private final ClockProxyRenderer carrierRenderer = new ClockProxyRenderer();
|
private final ClockProxyRenderer carrierRenderer = new ClockProxyRenderer();
|
||||||
private final UnlockedStockSourceCollector sourceCollector = new UnlockedStockSourceCollector();
|
private final UnlockedStockSourceCollector sourceCollector;
|
||||||
private final UnlockedVerticalOffsetScaler offsetScaler = new UnlockedVerticalOffsetScaler();
|
private final UnlockedVerticalOffsetScaler offsetScaler = new UnlockedVerticalOffsetScaler();
|
||||||
private final UnlockedChipPlacementController chipPlacementController;
|
private final UnlockedChipPlacementController chipPlacementController;
|
||||||
private final UnlockedLayoutPlanner layoutPlanner;
|
private final UnlockedLayoutPlanner layoutPlanner;
|
||||||
private final WeakHashMap<View, Integer> clockBaselineDeltaByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, Integer> clockBaselineDeltaByRoot = new WeakHashMap<>();
|
||||||
|
private final LinkedHashMap<Integer, Integer> clockSourceBaselineByRootKey = new LinkedHashMap<>();
|
||||||
private final WeakHashMap<View, LayoutInputSignature> lastLayoutSignatureByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, LayoutInputSignature> lastLayoutSignatureByRoot = new WeakHashMap<>();
|
||||||
private final WeakHashMap<View, CollectedIcons> lastCollectedIconsByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, CollectedIcons> lastCollectedIconsByRoot = new WeakHashMap<>();
|
||||||
private final WeakHashMap<View, LayoutPlan> lastLayoutPlanByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, LayoutPlan> lastLayoutPlanByRoot = new WeakHashMap<>();
|
||||||
private final WeakHashMap<View, Integer> lastClockGeometryByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, Integer> lastClockGeometryByRoot = new WeakHashMap<>();
|
||||||
private final WeakHashMap<View, Integer> lastClockSourceGeometryByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, Integer> lastClockSourceGeometryByRoot = new WeakHashMap<>();
|
||||||
private final WeakHashMap<View, Integer> lastClockAppearanceByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, Integer> lastClockAppearanceByRoot = new WeakHashMap<>();
|
||||||
|
private final WeakHashMap<View, Boolean> forcedChipRefreshByRoot = new WeakHashMap<>();
|
||||||
|
|
||||||
public UnlockedIconSnapshotRenderController() {
|
public UnlockedIconSnapshotRenderController() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UnlockedIconSnapshotRenderController(RuntimeContext runtimeContext) {
|
||||||
|
this.runtimeContext = runtimeContext;
|
||||||
|
sourceCollector = new UnlockedStockSourceCollector(runtimeContext);
|
||||||
statusRenderer = new SnapshotRenderer(true, true, false);
|
statusRenderer = new SnapshotRenderer(true, true, false);
|
||||||
notificationRenderer = new SnapshotRenderer(false, false, false);
|
notificationRenderer = new SnapshotRenderer(false, false, false);
|
||||||
chipRenderer = new SnapshotRenderer(false, false, true);
|
chipRenderer = new SnapshotRenderer(false, false, true);
|
||||||
chipPlacementController = new UnlockedChipPlacementController(chipRenderer, offsetScaler);
|
chipPlacementController = new UnlockedChipPlacementController(chipRenderer);
|
||||||
layoutPlanner = new UnlockedLayoutPlanner(
|
layoutPlanner = new UnlockedLayoutPlanner(
|
||||||
statusRenderer,
|
statusRenderer,
|
||||||
notificationRenderer,
|
notificationRenderer,
|
||||||
chipRenderer,
|
chipRenderer,
|
||||||
chipPlacementController,
|
chipPlacementController,
|
||||||
offsetScaler);
|
offsetScaler,
|
||||||
|
runtimeContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RenderResult renderUnlocked(
|
public RenderResult renderUnlocked(
|
||||||
@@ -60,7 +74,9 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
SceneKey scene,
|
SceneKey scene,
|
||||||
TextView externalCarrierView
|
TextView externalCarrierView
|
||||||
) {
|
) {
|
||||||
if (scene == null || (!scene.isUnlocked() && !scene.isLockscreen()) || !root.isAttachedToWindow()) {
|
if (scene == null
|
||||||
|
|| (!scene.isUnlocked() && !scene.isLockscreen() && !scene.isAod())
|
||||||
|
|| !root.isAttachedToWindow()) {
|
||||||
clearAll();
|
clearAll();
|
||||||
return new RenderResult(true, true);
|
return new RenderResult(true, true);
|
||||||
}
|
}
|
||||||
@@ -92,11 +108,14 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
anchors,
|
anchors,
|
||||||
previousIcons);
|
previousIcons);
|
||||||
LayoutInputSignature previousSignature = lastLayoutSignatureByRoot.get(root);
|
LayoutInputSignature previousSignature = lastLayoutSignatureByRoot.get(root);
|
||||||
|
boolean forceChipRefresh = Boolean.TRUE.equals(forcedChipRefreshByRoot.remove(root));
|
||||||
|
boolean sceneChanged = previousSignature != null
|
||||||
|
&& !java.util.Objects.equals(signature.scene, previousSignature.scene);
|
||||||
boolean stockSourcesChanged = previousSignature == null
|
boolean stockSourcesChanged = previousSignature == null
|
||||||
|| signature.stockSurfaceSignature() != previousSignature.stockSurfaceSignature();
|
|| signature.stockSurfaceSignature() != previousSignature.stockSurfaceSignature();
|
||||||
boolean chipSourcesChanged = previousSignature == null
|
boolean chipSourcesChanged = previousSignature == null
|
||||||
|| signature.chipSources != previousSignature.chipSources;
|
|| signature.chipSources != previousSignature.chipSources;
|
||||||
if (signature.equals(previousSignature)) {
|
if (signature.equals(previousSignature) && !forceChipRefresh) {
|
||||||
return new RenderResult(
|
return new RenderResult(
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -109,6 +128,7 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
ClockLayout currentClockLayout = null;
|
ClockLayout currentClockLayout = null;
|
||||||
Integer currentClockGeometry = null;
|
Integer currentClockGeometry = null;
|
||||||
if (isClockOnlySignatureChange(previousSignature, signature)
|
if (isClockOnlySignatureChange(previousSignature, signature)
|
||||||
|
&& !forceChipRefresh
|
||||||
&& scene.isUnlocked()
|
&& scene.isUnlocked()
|
||||||
&& settings.clockEnabledUnlocked
|
&& settings.clockEnabledUnlocked
|
||||||
&& previousIcons != null) {
|
&& previousIcons != null) {
|
||||||
@@ -158,8 +178,11 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CollectedIcons collectedIcons = previousIcons;
|
CollectedIcons collectedIcons = previousIcons;
|
||||||
if (stockSourcesChanged || collectedIcons == null) {
|
if (forceChipRefresh && collectedIcons != null) {
|
||||||
collectedIcons = sourceCollector.collect(root, anchors);
|
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
|
||||||
|
lastCollectedIconsByRoot.put(root, collectedIcons);
|
||||||
|
} else if (sceneChanged || stockSourcesChanged || collectedIcons == null) {
|
||||||
|
collectedIcons = sourceCollector.collect(root, anchors, scene);
|
||||||
lastCollectedIconsByRoot.put(root, collectedIcons);
|
lastCollectedIconsByRoot.put(root, collectedIcons);
|
||||||
} else if (chipSourcesChanged) {
|
} else if (chipSourcesChanged) {
|
||||||
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
|
collectedIcons = sourceCollector.collectChips(root, anchors, collectedIcons);
|
||||||
@@ -190,7 +213,6 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
settings,
|
settings,
|
||||||
currentClockLayout,
|
currentClockLayout,
|
||||||
scene);
|
scene);
|
||||||
lastLayoutPlanByRoot.put(root, layoutPlan);
|
|
||||||
lastClockGeometryByRoot.put(root, currentClockGeometry != null ? currentClockGeometry : 0);
|
lastClockGeometryByRoot.put(root, currentClockGeometry != null ? currentClockGeometry : 0);
|
||||||
lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry);
|
lastClockSourceGeometryByRoot.put(root, currentClockSourceGeometry);
|
||||||
layoutPlan = withCurrentDotColors(layoutPlan, collectedIcons);
|
layoutPlan = withCurrentDotColors(layoutPlan, collectedIcons);
|
||||||
@@ -200,7 +222,9 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
} else {
|
} else {
|
||||||
clockRenderer.clear(clockHost);
|
clockRenderer.clear(clockHost);
|
||||||
}
|
}
|
||||||
if (scene.isLockscreen() && settings.layoutCarrierEnabledLockscreen && layoutPlan.carrierPlacement != null) {
|
if (scene.isLockscreen()
|
||||||
|
&& settings.layoutCarrierEnabledLockscreen
|
||||||
|
&& layoutPlan.carrierPlacement != null) {
|
||||||
carrierRenderer.render(carrierHost, layoutPlan.carrierPlacement);
|
carrierRenderer.render(carrierHost, layoutPlan.carrierPlacement);
|
||||||
} else {
|
} else {
|
||||||
carrierRenderer.clear(carrierHost);
|
carrierRenderer.clear(carrierHost);
|
||||||
@@ -265,6 +289,32 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean refreshUnlockedChipContent(
|
||||||
|
View root,
|
||||||
|
ViewGroup chipHost,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
|
if (root == null
|
||||||
|
|| chipHost == null
|
||||||
|
|| scene == null
|
||||||
|
|| !scene.isUnlocked()
|
||||||
|
|| !root.isAttachedToWindow()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LayoutPlan layoutPlan = lastLayoutPlanByRoot.get(root);
|
||||||
|
if (layoutPlan == null
|
||||||
|
|| layoutPlan.chipPlacements == null
|
||||||
|
|| layoutPlan.chipPlacements.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
|
||||||
|
if (settings == null || !settings.layoutChipEnabledUnlocked) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
chipRenderer.renderPlacements(chipHost, layoutPlan.chipPlacements);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean refreshUnlockedClockText(
|
public boolean refreshUnlockedClockText(
|
||||||
View root,
|
View root,
|
||||||
ViewGroup clockHost,
|
ViewGroup clockHost,
|
||||||
@@ -273,7 +323,7 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
if (root == null
|
if (root == null
|
||||||
|| clockHost == null
|
|| clockHost == null
|
||||||
|| scene == null
|
|| scene == null
|
||||||
|| !scene.isUnlocked()
|
|| (!scene.isUnlocked() && !scene.isLockscreen())
|
||||||
|| !root.isAttachedToWindow()) {
|
|| !root.isAttachedToWindow()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -282,7 +332,7 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
|
SbtSettings settings = RuntimeSettingsCache.get(root.getContext());
|
||||||
if (settings == null || !settings.clockEnabledUnlocked) {
|
if (settings == null || !clockEnabledForScene(settings, scene)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CollectedIcons collectedIcons = lastCollectedIconsByRoot.get(root);
|
CollectedIcons collectedIcons = lastCollectedIconsByRoot.get(root);
|
||||||
@@ -355,9 +405,13 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
if (settings == null || scene == null) {
|
if (settings == null || scene == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return scene.isLockscreen()
|
if (scene.isLockscreen()) {
|
||||||
? settings.layoutStatusEnabledLockscreen
|
return settings.layoutStatusEnabledLockscreen;
|
||||||
: settings.layoutStatusEnabledUnlocked;
|
}
|
||||||
|
if (scene.isAod()) {
|
||||||
|
return settings.layoutStatusEnabledAod;
|
||||||
|
}
|
||||||
|
return settings.layoutStatusEnabledUnlocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean notificationsEnabledForScene(SbtSettings settings, SceneKey scene) {
|
private boolean notificationsEnabledForScene(SbtSettings settings, SceneKey scene) {
|
||||||
@@ -366,8 +420,14 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
}
|
}
|
||||||
if (scene.isLockscreen()) {
|
if (scene.isLockscreen()) {
|
||||||
return settings.layoutNotifEnabledLockscreen
|
return settings.layoutNotifEnabledLockscreen
|
||||||
&& scene.notificationDisplayStyle() != se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle.NONE
|
&& scene.notificationDisplayStyle() != NotificationDisplayStyle.NONE
|
||||||
&& scene.notificationDisplayStyle() != se.ajpanton.statusbartweak.runtime.mode.NotificationDisplayStyle.CARDS;
|
&& scene.notificationDisplayStyle() != NotificationDisplayStyle.CARDS;
|
||||||
|
}
|
||||||
|
if (scene.isAod()) {
|
||||||
|
NotificationDisplayStyle style = scene.notificationDisplayStyle();
|
||||||
|
return settings.layoutNotifEnabledAod
|
||||||
|
&& (style == NotificationDisplayStyle.ICONS
|
||||||
|
|| style == NotificationDisplayStyle.DOT);
|
||||||
}
|
}
|
||||||
return settings.layoutNotifEnabledUnlocked;
|
return settings.layoutNotifEnabledUnlocked;
|
||||||
}
|
}
|
||||||
@@ -556,6 +616,8 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
chipRenderer.clearAll();
|
chipRenderer.clearAll();
|
||||||
sourceCollector.clear();
|
sourceCollector.clear();
|
||||||
clockBaselineDeltaByRoot.clear();
|
clockBaselineDeltaByRoot.clear();
|
||||||
|
clockSourceBaselineByRootKey.clear();
|
||||||
|
forcedChipRefreshByRoot.clear();
|
||||||
lastLayoutSignatureByRoot.clear();
|
lastLayoutSignatureByRoot.clear();
|
||||||
lastCollectedIconsByRoot.clear();
|
lastCollectedIconsByRoot.clear();
|
||||||
lastLayoutPlanByRoot.clear();
|
lastLayoutPlanByRoot.clear();
|
||||||
@@ -565,9 +627,31 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
chipPlacementController.clear();
|
chipPlacementController.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clearRoot(View root) {
|
||||||
|
if (root == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
forcedChipRefreshByRoot.remove(root);
|
||||||
|
sourceCollector.clearRoot(root);
|
||||||
|
clockBaselineDeltaByRoot.remove(root);
|
||||||
|
lastLayoutSignatureByRoot.remove(root);
|
||||||
|
lastCollectedIconsByRoot.remove(root);
|
||||||
|
lastLayoutPlanByRoot.remove(root);
|
||||||
|
lastClockGeometryByRoot.remove(root);
|
||||||
|
lastClockSourceGeometryByRoot.remove(root);
|
||||||
|
lastClockAppearanceByRoot.remove(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceChipRefresh(View root) {
|
||||||
|
if (root != null) {
|
||||||
|
forcedChipRefreshByRoot.put(root, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void beginRootTransition() {
|
public void beginRootTransition() {
|
||||||
statusRenderer.beginTransitionHold();
|
statusRenderer.beginTransitionHold();
|
||||||
sourceCollector.clear();
|
sourceCollector.clear();
|
||||||
|
forcedChipRefreshByRoot.clear();
|
||||||
lastLayoutSignatureByRoot.clear();
|
lastLayoutSignatureByRoot.clear();
|
||||||
lastCollectedIconsByRoot.clear();
|
lastCollectedIconsByRoot.clear();
|
||||||
lastLayoutPlanByRoot.clear();
|
lastLayoutPlanByRoot.clear();
|
||||||
@@ -615,12 +699,12 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
if (model == null || model.isEmpty()) {
|
if (model == null || model.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
int baselineY = stableClockBaselineY(root, source, clockContainer);
|
||||||
return ClockLayout.measure(
|
return ClockLayout.measure(
|
||||||
source,
|
source,
|
||||||
model,
|
model,
|
||||||
UnlockedLayoutPlanner.positionFor(settings.clockPosition),
|
UnlockedLayoutPlanner.positionFor(settings.clockPosition),
|
||||||
stableClockBaselineY(root, source, clockContainer)
|
baselineY - offsetScaler.clock(settings.clockVerticalOffsetPx, source),
|
||||||
- offsetScaler.clock(settings.clockVerticalOffsetPx, source),
|
|
||||||
root.getWidth(),
|
root.getWidth(),
|
||||||
cutoutBounds,
|
cutoutBounds,
|
||||||
settings.clockMiddleAutoNearestSide,
|
settings.clockMiddleAutoNearestSide,
|
||||||
@@ -872,6 +956,7 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
int sourceBaseline = source.getBaseline() > 0
|
int sourceBaseline = source.getBaseline() > 0
|
||||||
? source.getBaseline()
|
? source.getBaseline()
|
||||||
: (sourceBounds != null ? Math.max(0, (sourceBounds.height * 3) / 4) : 0);
|
: (sourceBounds != null ? Math.max(0, (sourceBounds.height * 3) / 4) : 0);
|
||||||
|
sourceBaseline = stableClockSourceBaseline(root, source, sourceBaseline);
|
||||||
Bounds containerBounds = ViewGeometry.boundsRelativeTo(root, clockContainer);
|
Bounds containerBounds = ViewGeometry.boundsRelativeTo(root, clockContainer);
|
||||||
if (containerBounds != null
|
if (containerBounds != null
|
||||||
&& containerBounds.width > 0
|
&& containerBounds.width > 0
|
||||||
@@ -890,6 +975,28 @@ public final class UnlockedIconSnapshotRenderController {
|
|||||||
return sourceBounds != null ? sourceBounds.top + sourceBaseline : 0;
|
return sourceBounds != null ? sourceBounds.top + sourceBaseline : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int stableClockSourceBaseline(View root, TextView source, int sourceBaseline) {
|
||||||
|
if (root == null || source == null || root.getWidth() <= 0 || sourceBaseline <= 0) {
|
||||||
|
return sourceBaseline;
|
||||||
|
}
|
||||||
|
int key = 31 * root.getWidth() + Math.round(source.getTextSize());
|
||||||
|
Integer previous = clockSourceBaselineByRootKey.get(key);
|
||||||
|
int stable = previous == null ? sourceBaseline : Math.min(previous, sourceBaseline);
|
||||||
|
clockSourceBaselineByRootKey.put(key, stable);
|
||||||
|
while (clockSourceBaselineByRootKey.size() > 8) {
|
||||||
|
Integer eldest = null;
|
||||||
|
for (Map.Entry<Integer, Integer> entry : clockSourceBaselineByRootKey.entrySet()) {
|
||||||
|
eldest = entry.getKey();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (eldest == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clockSourceBaselineByRootKey.remove(eldest);
|
||||||
|
}
|
||||||
|
return stable;
|
||||||
|
}
|
||||||
|
|
||||||
public record RenderResult(
|
public record RenderResult(
|
||||||
boolean layoutChanged,
|
boolean layoutChanged,
|
||||||
boolean stockSourcesChanged,
|
boolean stockSourcesChanged,
|
||||||
|
|||||||
+143
-10
@@ -18,6 +18,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
final SnapshotRenderer renderer;
|
final SnapshotRenderer renderer;
|
||||||
final ArrayList<SnapshotPlacement> rawPlacements;
|
final ArrayList<SnapshotPlacement> rawPlacements;
|
||||||
final boolean showDotIfTruncated;
|
final boolean showDotIfTruncated;
|
||||||
|
final boolean forceOverflowDotOnly;
|
||||||
final Bounds reservedBounds;
|
final Bounds reservedBounds;
|
||||||
final ClockLayout clockLayout;
|
final ClockLayout clockLayout;
|
||||||
|
|
||||||
@@ -26,6 +27,8 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
Bounds placedBounds;
|
Bounds placedBounds;
|
||||||
int clipStartPx;
|
int clipStartPx;
|
||||||
int clipEndPx;
|
int clipEndPx;
|
||||||
|
private int solverCollisionTop = Integer.MIN_VALUE;
|
||||||
|
private int solverCollisionHeight = Integer.MIN_VALUE;
|
||||||
|
|
||||||
private UnlockedLayoutBand(
|
private UnlockedLayoutBand(
|
||||||
LayoutItemKind kind,
|
LayoutItemKind kind,
|
||||||
@@ -36,6 +39,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
boolean middleAutoNearestSide,
|
boolean middleAutoNearestSide,
|
||||||
AnchorSide middleSide,
|
AnchorSide middleSide,
|
||||||
boolean showDotIfTruncated,
|
boolean showDotIfTruncated,
|
||||||
|
boolean forceOverflowDotOnly,
|
||||||
Bounds reservedBounds,
|
Bounds reservedBounds,
|
||||||
ClockLayout clockLayout,
|
ClockLayout clockLayout,
|
||||||
SplitRegion splitRegion
|
SplitRegion splitRegion
|
||||||
@@ -45,6 +49,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
this.rawPlacements = rawPlacements;
|
this.rawPlacements = rawPlacements;
|
||||||
this.showDotIfTruncated = showDotIfTruncated;
|
this.showDotIfTruncated = showDotIfTruncated;
|
||||||
|
this.forceOverflowDotOnly = forceOverflowDotOnly;
|
||||||
this.reservedBounds = reservedBounds;
|
this.reservedBounds = reservedBounds;
|
||||||
this.clockLayout = clockLayout;
|
this.clockLayout = clockLayout;
|
||||||
}
|
}
|
||||||
@@ -64,6 +69,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
settings.clockMiddleAutoNearestSide,
|
settings.clockMiddleAutoNearestSide,
|
||||||
sideFor(settings.clockMiddleCutoutSide),
|
sideFor(settings.clockMiddleCutoutSide),
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null,
|
null,
|
||||||
clockLayout,
|
clockLayout,
|
||||||
SplitRegion.NONE);
|
SplitRegion.NONE);
|
||||||
@@ -84,6 +90,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
settings.clockMiddleAutoNearestSide,
|
settings.clockMiddleAutoNearestSide,
|
||||||
sideFor(settings.clockMiddleCutoutSide),
|
sideFor(settings.clockMiddleCutoutSide),
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null,
|
null,
|
||||||
clockLayout,
|
clockLayout,
|
||||||
splitRegion);
|
splitRegion);
|
||||||
@@ -105,6 +112,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
middleAutoNearestSide,
|
middleAutoNearestSide,
|
||||||
middleSide,
|
middleSide,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null,
|
null,
|
||||||
carrierLayout,
|
carrierLayout,
|
||||||
SplitRegion.NONE);
|
SplitRegion.NONE);
|
||||||
@@ -129,6 +137,37 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
middleAutoNearestSide,
|
middleAutoNearestSide,
|
||||||
middleSide,
|
middleSide,
|
||||||
showDotIfTruncated,
|
showDotIfTruncated,
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
SplitRegion.NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockedLayoutBand withSolverCollision(int top, int height) {
|
||||||
|
solverCollisionTop = top;
|
||||||
|
solverCollisionHeight = Math.max(0, height);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static UnlockedLayoutBand dotIcons(
|
||||||
|
LayoutItemKind kind,
|
||||||
|
ViewGroup host,
|
||||||
|
SnapshotRenderer renderer,
|
||||||
|
ArrayList<SnapshotPlacement> rawPlacements,
|
||||||
|
LayoutPosition position,
|
||||||
|
boolean middleAutoNearestSide,
|
||||||
|
AnchorSide middleSide
|
||||||
|
) {
|
||||||
|
return new UnlockedLayoutBand(
|
||||||
|
kind,
|
||||||
|
host,
|
||||||
|
renderer,
|
||||||
|
rawPlacements,
|
||||||
|
position,
|
||||||
|
middleAutoNearestSide,
|
||||||
|
middleSide,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
SplitRegion.NONE);
|
SplitRegion.NONE);
|
||||||
@@ -201,6 +240,16 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
if (kind != LayoutItemKind.NOTIFICATIONS && kind != LayoutItemKind.STATUS) {
|
if (kind != LayoutItemKind.NOTIFICATIONS && kind != LayoutItemKind.STATUS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (forceOverflowDotOnly) {
|
||||||
|
int height = dotHeight(rawPlacements);
|
||||||
|
SnapshotPlacement dotPlacement = dotPlacement(
|
||||||
|
Math.max(1, Math.round(Math.max(1, height) * 0.75f)),
|
||||||
|
height,
|
||||||
|
rowTop(rawPlacements));
|
||||||
|
placements = new ArrayList<>();
|
||||||
|
placements.add(dotPlacement);
|
||||||
|
return;
|
||||||
|
}
|
||||||
int targetVisible = Math.max(0, visibleIcons);
|
int targetVisible = Math.max(0, visibleIcons);
|
||||||
placements = iconSlice(rawPlacements, firstIconIndex, targetVisible);
|
placements = iconSlice(rawPlacements, firstIconIndex, targetVisible);
|
||||||
if (dot) {
|
if (dot) {
|
||||||
@@ -295,7 +344,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
withoutDot.add(placement);
|
withoutDot.add(placement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SnapshotPlacement dotPlacement = dotPlacement(width, height);
|
SnapshotPlacement dotPlacement = dotPlacement(width, height, rowTop(withoutDot));
|
||||||
if (kind == LayoutItemKind.STATUS) {
|
if (kind == LayoutItemKind.STATUS) {
|
||||||
withoutDot.add(0, dotPlacement);
|
withoutDot.add(0, dotPlacement);
|
||||||
} else {
|
} else {
|
||||||
@@ -417,6 +466,25 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
return boxes;
|
return boxes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayList<Bounds> solverCollisionBoxes() {
|
||||||
|
ArrayList<Bounds> boxes = collisionBoxes();
|
||||||
|
if (isTextKind()
|
||||||
|
|| solverCollisionTop == Integer.MIN_VALUE
|
||||||
|
|| solverCollisionHeight <= 0
|
||||||
|
|| boxes.isEmpty()) {
|
||||||
|
return boxes;
|
||||||
|
}
|
||||||
|
ArrayList<Bounds> solverBoxes = new ArrayList<>();
|
||||||
|
for (Bounds box : boxes) {
|
||||||
|
solverBoxes.add(new Bounds(
|
||||||
|
box.left,
|
||||||
|
solverCollisionTop,
|
||||||
|
box.width,
|
||||||
|
solverCollisionHeight));
|
||||||
|
}
|
||||||
|
return solverBoxes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ArrayList<Bounds> placedCollisionBounds() {
|
protected ArrayList<Bounds> placedCollisionBounds() {
|
||||||
ArrayList<Bounds> boxes = new ArrayList<>();
|
ArrayList<Bounds> boxes = new ArrayList<>();
|
||||||
@@ -454,8 +522,8 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
private int overflowDotVisualWidth(SnapshotPlacement placement) {
|
private int overflowDotVisualWidth(SnapshotPlacement placement) {
|
||||||
Bounds bounds = placement.bounds;
|
Bounds bounds = placement.bounds;
|
||||||
int base = Math.max(1, Math.min(bounds.width, bounds.height));
|
int base = Math.max(1, Math.min(bounds.width, bounds.height));
|
||||||
int radius = Math.max(1, Math.round(base * 0.16f));
|
int radius = Math.max(1, Math.round(base * 0.125f));
|
||||||
return Math.min(bounds.width, radius * 2 + 2);
|
return Math.min(bounds.width, radius * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bounds collisionBounds(SnapshotPlacement placement) {
|
private Bounds collisionBounds(SnapshotPlacement placement) {
|
||||||
@@ -487,7 +555,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
boolean hadDot = hasOverflowDot(icons);
|
boolean hadDot = hasOverflowDot(icons);
|
||||||
icons.remove(removeIndex);
|
icons.remove(removeIndex);
|
||||||
if (showDotIfTruncated && !hadDot) {
|
if (showDotIfTruncated && !hadDot) {
|
||||||
SnapshotPlacement dot = dotPlacement(dotWidth(icons), dotHeight(icons));
|
SnapshotPlacement dot = dotPlacement(dotWidth(icons), dotHeight(icons), rowTop(icons));
|
||||||
if (fromStart) {
|
if (fromStart) {
|
||||||
icons.add(0, dot);
|
icons.add(0, dot);
|
||||||
} else {
|
} else {
|
||||||
@@ -604,17 +672,61 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SnapshotPlacement dotPlacement(int width, int height) {
|
private int rowTop(ArrayList<SnapshotPlacement> preferred) {
|
||||||
|
int top = rowTop(preferred, true);
|
||||||
|
if (top != Integer.MAX_VALUE) {
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
top = rowTop(rawPlacements, true);
|
||||||
|
if (top != Integer.MAX_VALUE) {
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
top = rowTop(preferred, false);
|
||||||
|
if (top != Integer.MAX_VALUE) {
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
top = rowTop(rawPlacements, false);
|
||||||
|
return top != Integer.MAX_VALUE ? top : top();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int rowTop(ArrayList<SnapshotPlacement> placements, boolean shrinkableOnly) {
|
||||||
|
if (placements == null || placements.isEmpty()) {
|
||||||
|
return Integer.MAX_VALUE;
|
||||||
|
}
|
||||||
|
int top = Integer.MAX_VALUE;
|
||||||
|
for (SnapshotPlacement placement : placements) {
|
||||||
|
if (placement == null || (shrinkableOnly && !isShrinkableIcon(placement))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
top = Math.min(top, collisionBounds(placement).top);
|
||||||
|
}
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SnapshotPlacement dotPlacement(int width, int height, int rowTop) {
|
||||||
|
int safeWidth = Math.max(1, width);
|
||||||
|
int safeHeight = Math.max(1, height);
|
||||||
return new SnapshotPlacement(
|
return new SnapshotPlacement(
|
||||||
null,
|
null,
|
||||||
new Bounds(0, top(), Math.max(1, width), Math.max(1, height)),
|
new Bounds(0, rowTop, safeWidth, safeHeight),
|
||||||
SnapshotKeys.OVERFLOW_DOT + ":" + kind.name().toLowerCase(java.util.Locale.ROOT),
|
SnapshotKeys.OVERFLOW_DOT + ":" + kind.name().toLowerCase(java.util.Locale.ROOT),
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
dotColor(),
|
dotColor(),
|
||||||
null,
|
null,
|
||||||
new Bounds(0, 0, Math.max(1, width), Math.max(1, height)),
|
new Bounds(0, 0, safeWidth, safeHeight),
|
||||||
0);
|
dotCenterOffsetX(safeWidth, safeHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int dotCenterOffsetX(int width, int height) {
|
||||||
|
int fullWidth = Math.max(1, Math.round(Math.max(1, height) * 0.75f));
|
||||||
|
if (width >= fullWidth) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
float radius = Math.max(1f, Math.min(width / 2f, height * 0.125f));
|
||||||
|
float centered = width / 2f;
|
||||||
|
float target = kind == LayoutItemKind.STATUS ? radius : width - radius;
|
||||||
|
return Math.round(target - centered);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int dotColor() {
|
private int dotColor() {
|
||||||
@@ -649,7 +761,7 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
int height = Math.max(1, dotHeight(activePlacements()));
|
int height = Math.max(1, dotHeight(activePlacements()));
|
||||||
return new SnapshotPlacement(
|
return new SnapshotPlacement(
|
||||||
null,
|
null,
|
||||||
new Bounds(0, top(), 1, height),
|
new Bounds(0, rowTop(activePlacements()), 1, height),
|
||||||
SnapshotKeys.EMPTY_ICON_CONTAINER + ":" + kind.name().toLowerCase(java.util.Locale.ROOT),
|
SnapshotKeys.EMPTY_ICON_CONTAINER + ":" + kind.name().toLowerCase(java.util.Locale.ROOT),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
@@ -689,6 +801,14 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
collisionWidth,
|
collisionWidth,
|
||||||
placement.contentBounds.height)
|
placement.contentBounds.height)
|
||||||
: null;
|
: null;
|
||||||
|
Bounds sourceRenderBounds = placement.sourceRenderBounds;
|
||||||
|
int sourceOffsetX = placement.sourceOffsetX + removeLeft;
|
||||||
|
if (kind == LayoutItemKind.CHIP && sourceRenderBounds != null && clippedContent != null) {
|
||||||
|
sourceRenderBounds = chipSourceRenderBounds(
|
||||||
|
sourceRenderBounds,
|
||||||
|
clippedContent);
|
||||||
|
sourceOffsetX = 0;
|
||||||
|
}
|
||||||
return new SnapshotPlacement(
|
return new SnapshotPlacement(
|
||||||
placement.source,
|
placement.source,
|
||||||
clippedBounds,
|
clippedBounds,
|
||||||
@@ -698,7 +818,20 @@ final class UnlockedLayoutBand extends StatusBarLayoutSolver.LayoutBand {
|
|||||||
placement.overflowDotColor,
|
placement.overflowDotColor,
|
||||||
placement.heldSignal,
|
placement.heldSignal,
|
||||||
clippedContent,
|
clippedContent,
|
||||||
placement.sourceOffsetX + removeLeft);
|
sourceOffsetX,
|
||||||
|
sourceRenderBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds chipSourceRenderBounds(Bounds sourceRenderBounds, Bounds clippedContent) {
|
||||||
|
if (sourceRenderBounds == null || clippedContent == null) {
|
||||||
|
return sourceRenderBounds;
|
||||||
|
}
|
||||||
|
int width = Math.max(1, clippedContent.left + clippedContent.width);
|
||||||
|
return new Bounds(
|
||||||
|
sourceRenderBounds.left,
|
||||||
|
sourceRenderBounds.top,
|
||||||
|
width,
|
||||||
|
sourceRenderBounds.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int sumWidths(ArrayList<SnapshotPlacement> snapshotPlacements) {
|
private int sumWidths(ArrayList<SnapshotPlacement> snapshotPlacements) {
|
||||||
|
|||||||
+827
-108
File diff suppressed because it is too large
Load Diff
+565
-19
@@ -2,6 +2,7 @@ package se.ajpanton.statusbartweak.runtime.render;
|
|||||||
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
@@ -9,20 +10,36 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
import se.ajpanton.statusbartweak.runtime.features.RuntimeContext;
|
||||||
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.SceneKey;
|
import se.ajpanton.statusbartweak.runtime.mode.SceneKey;
|
||||||
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
import se.ajpanton.statusbartweak.shell.settings.SbtSettings;
|
||||||
|
|
||||||
final class UnlockedStockSourceCollector {
|
final class UnlockedStockSourceCollector {
|
||||||
private final WeakHashMap<View, RootAnchors> anchorsByRoot = new WeakHashMap<>();
|
private final WeakHashMap<View, RootAnchors> anchorsByRoot = new WeakHashMap<>();
|
||||||
|
|
||||||
|
UnlockedStockSourceCollector() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockedStockSourceCollector(RuntimeContext runtimeContext) {
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
anchorsByRoot.clear();
|
anchorsByRoot.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clearRoot(View root) {
|
||||||
|
if (root != null) {
|
||||||
|
anchorsByRoot.remove(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RootAnchors anchorsFor(View root) {
|
RootAnchors anchorsFor(View root) {
|
||||||
RootAnchors cached = anchorsByRoot.get(root);
|
RootAnchors cached = anchorsByRoot.get(root);
|
||||||
if (cached != null && cached.isUsable()) {
|
if (cached != null && cached.isUsable()) {
|
||||||
@@ -37,21 +54,40 @@ final class UnlockedStockSourceCollector {
|
|||||||
return anchors;
|
return anchors;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectedIcons collect(View root, RootAnchors anchors) {
|
CollectedIcons collect(View root, RootAnchors anchors, SceneKey scene) {
|
||||||
ArrayList<SnapshotSource> statusIcons = new ArrayList<>();
|
ArrayList<SnapshotSource> statusIcons = new ArrayList<>();
|
||||||
ArrayList<SnapshotSource> notificationIcons = new ArrayList<>();
|
ArrayList<SnapshotSource> notificationIcons = new ArrayList<>();
|
||||||
ArrayList<SnapshotSource> statusChips = new ArrayList<>();
|
ArrayList<SnapshotSource> statusChips = new ArrayList<>();
|
||||||
ArrayList<SnapshotSource> statusChipMetrics = new ArrayList<>();
|
ArrayList<SnapshotSource> statusChipMetrics = new ArrayList<>();
|
||||||
|
if (scene != null && scene.isAod()) {
|
||||||
|
collectAodStatusSnapshotViews(root, statusIcons, scene);
|
||||||
|
}
|
||||||
|
if (statusIcons.isEmpty()) {
|
||||||
if (anchors.statusRoot != null) {
|
if (anchors.statusRoot != null) {
|
||||||
collectStatusSnapshotViews(anchors.statusRoot, statusIcons);
|
collectStatusSnapshotViews(anchors.statusRoot, statusIcons);
|
||||||
|
} else if (scene != null && scene.isAod()) {
|
||||||
|
collectStatusSnapshotViews(root, statusIcons);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scene == null || !scene.isAod()) {
|
||||||
|
mergeActiveHiddenStatusSources(root, anchors.statusIcons, statusIcons);
|
||||||
}
|
}
|
||||||
if (anchors.battery != null && !isDescendantOf(anchors.battery, anchors.statusRoot)) {
|
if (anchors.battery != null && !isDescendantOf(anchors.battery, anchors.statusRoot)) {
|
||||||
collectStatusSnapshotViews(anchors.battery, statusIcons);
|
collectStatusSnapshotViews(anchors.battery, statusIcons);
|
||||||
}
|
}
|
||||||
if (anchors.notificationRoot != null) {
|
normalizeStatusIconSourceBounds(root, statusIcons);
|
||||||
|
if (scene != null && scene.isAod()) {
|
||||||
|
if (scene.notificationDisplayStyle() == NotificationDisplayStyle.ICONS
|
||||||
|
|| scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT) {
|
||||||
|
notificationIcons.addAll(
|
||||||
|
LockscreenCardsNotificationIconSourceStore.snapshotSourcesForAodIconsRoot(root));
|
||||||
|
}
|
||||||
|
} else if (anchors.notificationRoot != null) {
|
||||||
collectNotificationSnapshotViews(anchors.notificationRoot, notificationIcons);
|
collectNotificationSnapshotViews(anchors.notificationRoot, notificationIcons);
|
||||||
}
|
}
|
||||||
|
if (scene == null || scene.isUnlocked()) {
|
||||||
collectStatusChipSnapshotViews(root, statusChips, statusChipMetrics);
|
collectStatusChipSnapshotViews(root, statusChips, statusChipMetrics);
|
||||||
|
}
|
||||||
return new CollectedIcons(
|
return new CollectedIcons(
|
||||||
anchors.clockView,
|
anchors.clockView,
|
||||||
statusIcons,
|
statusIcons,
|
||||||
@@ -61,6 +97,53 @@ final class UnlockedStockSourceCollector {
|
|||||||
anchors.carrierView);
|
anchors.carrierView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void collectAodStatusSnapshotViews(
|
||||||
|
View root,
|
||||||
|
ArrayList<SnapshotSource> out,
|
||||||
|
SceneKey scene
|
||||||
|
) {
|
||||||
|
if (root == null || out == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean iconMode = scene != null
|
||||||
|
&& (scene.notificationDisplayStyle() == NotificationDisplayStyle.ICONS
|
||||||
|
|| scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT);
|
||||||
|
View excludedNotificationContainer = iconMode
|
||||||
|
? LockscreenCardsNotificationIconSourceStore.sourceContainerForAodIconsRoot(root)
|
||||||
|
: LockscreenCardsNotificationIconSourceStore.sourceContainerForRoot(root);
|
||||||
|
for (View source : AodStatusbarSourceStore.statusSourcesForRoot(
|
||||||
|
root,
|
||||||
|
excludedNotificationContainer)) {
|
||||||
|
collectStatusSnapshotViews(source, out, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String reflectString(View view, String methodName, String... fieldNames) {
|
||||||
|
Object methodValue = ReflectionSupport.invokeMethod(view, methodName, new Class<?>[0]);
|
||||||
|
if (methodValue != null) {
|
||||||
|
return safeText(String.valueOf(methodValue));
|
||||||
|
}
|
||||||
|
if (fieldNames != null) {
|
||||||
|
for (String fieldName : fieldNames) {
|
||||||
|
Object fieldValue = ReflectionSupport.getFieldValue(view, fieldName);
|
||||||
|
if (fieldValue != null) {
|
||||||
|
return safeText(String.valueOf(fieldValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String safeText(Object value) {
|
||||||
|
if (value == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return String.valueOf(value)
|
||||||
|
.replace('\n', ' ')
|
||||||
|
.replace('\r', ' ')
|
||||||
|
.replace(';', ',');
|
||||||
|
}
|
||||||
|
|
||||||
CollectedIcons collectChips(
|
CollectedIcons collectChips(
|
||||||
View root,
|
View root,
|
||||||
RootAnchors anchors,
|
RootAnchors anchors,
|
||||||
@@ -89,9 +172,17 @@ final class UnlockedStockSourceCollector {
|
|||||||
RootAnchors anchors,
|
RootAnchors anchors,
|
||||||
CollectedIcons previousIcons
|
CollectedIcons previousIcons
|
||||||
) {
|
) {
|
||||||
int chipSourceSignature = settings.layoutChipEnabledUnlocked
|
int chipSourceSignature = scene != null
|
||||||
|
&& scene.isUnlocked()
|
||||||
|
&& settings.layoutChipEnabledUnlocked
|
||||||
? chipSourceSignature(root, previousIcons)
|
? chipSourceSignature(root, previousIcons)
|
||||||
: 0;
|
: 0;
|
||||||
|
int statusSourceSignature = sourceLayoutListSignature(
|
||||||
|
previousIcons != null ? previousIcons.statusIcons : null);
|
||||||
|
if (scene != null && scene.isAod()) {
|
||||||
|
statusSourceSignature = 31 * statusSourceSignature
|
||||||
|
+ aodLayoutAnchorSignature(root, anchors, scene);
|
||||||
|
}
|
||||||
return new LayoutInputSignature(
|
return new LayoutInputSignature(
|
||||||
scene != null ? scene.toString() : "",
|
scene != null ? scene.toString() : "",
|
||||||
root.getWidth(),
|
root.getWidth(),
|
||||||
@@ -102,7 +193,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,
|
||||||
layoutSettingsSignature(settings),
|
loggingAwareSettingsSignature(root, settings),
|
||||||
clockTimeSignature(settings),
|
clockTimeSignature(settings),
|
||||||
viewSignatureOrZero(anchors != null ? anchors.clockView : null),
|
viewSignatureOrZero(anchors != null ? anchors.clockView : null),
|
||||||
shallowTreeSignature(anchors != null ? anchors.clockContainer : null),
|
shallowTreeSignature(anchors != null ? anchors.clockContainer : null),
|
||||||
@@ -120,11 +211,36 @@ final class UnlockedStockSourceCollector {
|
|||||||
anchors != null ? anchors.clockContainer : null),
|
anchors != null ? anchors.clockContainer : null),
|
||||||
notificationRootSignature(anchors != null ? anchors.notificationRoot : null),
|
notificationRootSignature(anchors != null ? anchors.notificationRoot : null),
|
||||||
viewSignatureOrZero(anchors != null ? anchors.carrierView : null),
|
viewSignatureOrZero(anchors != null ? anchors.carrierView : null),
|
||||||
sourceLayoutListSignature(previousIcons != null ? previousIcons.statusIcons : null),
|
statusSourceSignature,
|
||||||
sourceLayoutListSignature(previousIcons != null ? previousIcons.notificationIcons : null),
|
sourceLayoutListSignature(previousIcons != null ? previousIcons.notificationIcons : null),
|
||||||
chipSourceSignature);
|
chipSourceSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int aodLayoutAnchorSignature(View root, RootAnchors anchors, SceneKey scene) {
|
||||||
|
if (root == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
boolean iconMode = scene != null
|
||||||
|
&& (scene.notificationDisplayStyle() == NotificationDisplayStyle.ICONS
|
||||||
|
|| scene.notificationDisplayStyle() == NotificationDisplayStyle.DOT);
|
||||||
|
View notificationContainer = iconMode
|
||||||
|
? LockscreenCardsNotificationIconSourceStore.sourceContainerForAodIconsRoot(root)
|
||||||
|
: LockscreenCardsNotificationIconSourceStore.sourceContainerForRoot(root);
|
||||||
|
Bounds notificationBounds = iconMode
|
||||||
|
? LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForAodIconsRoot(root)
|
||||||
|
: LockscreenCardsNotificationIconSourceStore.sourceContainerBoundsForRoot(root);
|
||||||
|
if (!iconMode && notificationBounds == null) {
|
||||||
|
notificationBounds = ViewGeometry.boundsRelativeTo(
|
||||||
|
root,
|
||||||
|
anchors != null ? anchors.notificationRoot : null);
|
||||||
|
}
|
||||||
|
Bounds statusBounds = AodStatusbarSourceStore.statusBoundsForRoot(root, notificationContainer);
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + boundsSignature(notificationBounds);
|
||||||
|
result = 31 * result + boundsSignature(statusBounds);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private void collectKnownStatusChipSnapshotViews(
|
private void collectKnownStatusChipSnapshotViews(
|
||||||
View root,
|
View root,
|
||||||
CollectedIcons previousIcons,
|
CollectedIcons previousIcons,
|
||||||
@@ -136,8 +252,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
if (previousIcons.statusChips != null) {
|
if (previousIcons.statusChips != null) {
|
||||||
for (SnapshotSource source : previousIcons.statusChips) {
|
for (SnapshotSource source : previousIcons.statusChips) {
|
||||||
View view = source.view();
|
if (isKnownStatusChipSnapshotSource(root, source)) {
|
||||||
if (isStatusChipSnapshotCandidate(root, view)) {
|
|
||||||
visibleOut.add(source);
|
visibleOut.add(source);
|
||||||
metricOut.add(source);
|
metricOut.add(source);
|
||||||
return;
|
return;
|
||||||
@@ -146,7 +261,13 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
if (previousIcons.statusChipMetrics != null) {
|
if (previousIcons.statusChipMetrics != null) {
|
||||||
for (SnapshotSource source : previousIcons.statusChipMetrics) {
|
for (SnapshotSource source : previousIcons.statusChipMetrics) {
|
||||||
if (isStatusChipMetricCandidate(root, source.view())) {
|
if (isKnownStatusChipSnapshotSource(root, source)) {
|
||||||
|
visibleOut.add(statusChipSource(root, source.view()));
|
||||||
|
metricOut.add(statusChipSource(root, source.view()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isStatusChipMetricCandidate(root, source.view(), true)
|
||||||
|
&& hasVisibleStatusChipContent(source.view())) {
|
||||||
metricOut.add(source);
|
metricOut.add(source);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -191,7 +312,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
if (battery == null && idName.equals("battery")) {
|
if (battery == null && idName.equals("battery")) {
|
||||||
battery = view;
|
battery = view;
|
||||||
}
|
}
|
||||||
if (notificationRoot == null && idName.equals("notificationIcons")) {
|
if (notificationRoot == null && isNotificationRootCandidate(view, idName)) {
|
||||||
notificationRoot = view;
|
notificationRoot = view;
|
||||||
}
|
}
|
||||||
if (carrierView == null && view instanceof TextView textView && isCarrierTextView(textView)) {
|
if (carrierView == null && view instanceof TextView textView && isCarrierTextView(textView)) {
|
||||||
@@ -252,8 +373,35 @@ final class UnlockedStockSourceCollector {
|
|||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isNotificationRootCandidate(View view, String idName) {
|
||||||
|
if (idName.equals("notificationIcons")
|
||||||
|
|| idName.equals("notification_icononly_container")
|
||||||
|
|| idName.equals("notification_icononly_area")
|
||||||
|
|| idName.equals("keyguard_icononly_container_view")
|
||||||
|
|| idName.equals("common_notification_widget")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String className = view != null ? view.getClass().getName() : "";
|
||||||
|
return className.contains("NotificationIconsOnlyContainer")
|
||||||
|
|| className.contains("SecShelfNotificationIconContainer");
|
||||||
|
}
|
||||||
|
|
||||||
private void collectStatusSnapshotViews(View source, ArrayList<SnapshotSource> out) {
|
private void collectStatusSnapshotViews(View source, ArrayList<SnapshotSource> out) {
|
||||||
|
collectStatusSnapshotViews(source, out, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void collectStatusSnapshotViews(
|
||||||
|
View source,
|
||||||
|
ArrayList<SnapshotSource> out,
|
||||||
|
boolean includeHidden
|
||||||
|
) {
|
||||||
|
if (isOwnedRuntimeView(source)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
boolean candidate = isStatusSnapshotCandidate(source);
|
boolean candidate = isStatusSnapshotCandidate(source);
|
||||||
|
if (includeHidden) {
|
||||||
|
candidate = isStatusSnapshotCandidate(source, true);
|
||||||
|
}
|
||||||
if (isModernSignalContainer(source)) {
|
if (isModernSignalContainer(source)) {
|
||||||
if (candidate) {
|
if (candidate) {
|
||||||
out.add(new SnapshotSource(source, SnapshotMode.VIEW));
|
out.add(new SnapshotSource(source, SnapshotMode.VIEW));
|
||||||
@@ -268,11 +416,269 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
if (source instanceof ViewGroup group) {
|
if (source instanceof ViewGroup group) {
|
||||||
for (int i = 0; i < group.getChildCount(); i++) {
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
collectStatusSnapshotViews(group.getChildAt(i), out);
|
collectStatusSnapshotViews(group.getChildAt(i), out, includeHidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void mergeActiveHiddenStatusSources(
|
||||||
|
View root,
|
||||||
|
View statusIcons,
|
||||||
|
ArrayList<SnapshotSource> out
|
||||||
|
) {
|
||||||
|
if (root == null || statusIcons == null || out == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArrayList<String> activeSlots = StatusIconSlotVisibilityStore.activeSlotList();
|
||||||
|
if (activeSlots.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LinkedHashMap<String, SnapshotSource> existingBySlot = new LinkedHashMap<>();
|
||||||
|
for (SnapshotSource source : out) {
|
||||||
|
if (source != null && isDescendantOf(source.view(), statusIcons)) {
|
||||||
|
String slot = reflectString(source.view(), "getSlot", "mSlot", "slot");
|
||||||
|
if (!slot.isEmpty()) {
|
||||||
|
existingBySlot.put(slot, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LinkedHashMap<String, View> childBySlot = new LinkedHashMap<>();
|
||||||
|
for (View child : directChildren(statusIcons)) {
|
||||||
|
String slot = reflectString(child, "getSlot", "mSlot", "slot");
|
||||||
|
if (!slot.isEmpty() && isDrawableStatusIconView(child)) {
|
||||||
|
childBySlot.put(slot, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArrayList<SnapshotSource> mergedStatusIcons = new ArrayList<>();
|
||||||
|
int syntheticIndex = 0;
|
||||||
|
Bounds metricBounds = representativeStatusIconBounds(root, statusIcons, out);
|
||||||
|
int size = Math.max(1, metricBounds.height);
|
||||||
|
for (String slot : activeSlots) {
|
||||||
|
SnapshotSource existing = existingBySlot.get(slot);
|
||||||
|
if (existing != null) {
|
||||||
|
SnapshotSource ordered = orderedStatusSource(
|
||||||
|
root,
|
||||||
|
existing,
|
||||||
|
metricBounds,
|
||||||
|
syntheticIndex,
|
||||||
|
size);
|
||||||
|
mergedStatusIcons.add(ordered);
|
||||||
|
syntheticIndex++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
View child = childBySlot.get(slot);
|
||||||
|
if (child == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int width = syntheticStatusIconWidth(child, size);
|
||||||
|
int height = syntheticStatusIconHeight(child, size);
|
||||||
|
Bounds bounds = orderedStatusBounds(metricBounds, syntheticIndex, width, height);
|
||||||
|
mergedStatusIcons.add(new SnapshotSource(
|
||||||
|
child,
|
||||||
|
SnapshotMode.VIEW,
|
||||||
|
slot,
|
||||||
|
bounds));
|
||||||
|
syntheticIndex++;
|
||||||
|
}
|
||||||
|
if (mergedStatusIcons.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ArrayList<SnapshotSource> merged = new ArrayList<>();
|
||||||
|
boolean inserted = false;
|
||||||
|
for (SnapshotSource source : out) {
|
||||||
|
if (source != null && isDescendantOf(source.view(), statusIcons)) {
|
||||||
|
if (!inserted) {
|
||||||
|
merged.addAll(mergedStatusIcons);
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
merged.add(source);
|
||||||
|
}
|
||||||
|
if (!inserted) {
|
||||||
|
merged.addAll(mergedStatusIcons);
|
||||||
|
}
|
||||||
|
out.clear();
|
||||||
|
out.addAll(merged);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SnapshotSource orderedStatusSource(
|
||||||
|
View root,
|
||||||
|
SnapshotSource source,
|
||||||
|
Bounds metricBounds,
|
||||||
|
int index,
|
||||||
|
int fallbackSize
|
||||||
|
) {
|
||||||
|
Bounds sourceBounds = ViewGeometry.boundsRelativeTo(root, source.view());
|
||||||
|
int width = sourceBounds != null && sourceBounds.width > 0
|
||||||
|
? sourceBounds.width
|
||||||
|
: fallbackSize;
|
||||||
|
int height = sourceBounds != null && sourceBounds.height > 0
|
||||||
|
? sourceBounds.height
|
||||||
|
: fallbackSize;
|
||||||
|
return new SnapshotSource(
|
||||||
|
source.view(),
|
||||||
|
source.mode(),
|
||||||
|
source.keyHint(),
|
||||||
|
orderedStatusBounds(metricBounds, index, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds orderedStatusBounds(
|
||||||
|
Bounds metricBounds,
|
||||||
|
int index,
|
||||||
|
int width,
|
||||||
|
int height
|
||||||
|
) {
|
||||||
|
int fallbackHeight = Math.max(1, metricBounds.height);
|
||||||
|
return new Bounds(
|
||||||
|
metricBounds.left + Math.max(0, index) * fallbackHeight,
|
||||||
|
metricBounds.top,
|
||||||
|
Math.max(1, width),
|
||||||
|
Math.max(1, height));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int syntheticStatusIconWidth(View view, int fallbackSize) {
|
||||||
|
int width = measuredWidth(view);
|
||||||
|
if (width > 0) {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
int drawableWidth = drawableWidth(view);
|
||||||
|
if (drawableWidth > 0) {
|
||||||
|
return normalizedStatusIconWidth(drawableWidth, fallbackSize);
|
||||||
|
}
|
||||||
|
return Math.max(1, fallbackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeStatusIconSourceBounds(View root, ArrayList<SnapshotSource> sources) {
|
||||||
|
if (root == null || sources == null || sources.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sources.size(); i++) {
|
||||||
|
SnapshotSource source = sources.get(i);
|
||||||
|
if (source == null || source.mode() != SnapshotMode.VIEW || !isDrawableStatusIconView(source.view())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds bounds = source.boundsOverride() != null
|
||||||
|
? source.boundsOverride()
|
||||||
|
: ViewGeometry.boundsRelativeTo(root, source.view());
|
||||||
|
if (bounds == null || bounds.height <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int drawableWidth = drawableWidth(source.view());
|
||||||
|
if (drawableWidth <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int width = normalizedStatusIconWidth(drawableWidth, bounds.height);
|
||||||
|
if (width == bounds.width) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sources.set(i, new SnapshotSource(
|
||||||
|
source.view(),
|
||||||
|
source.mode(),
|
||||||
|
source.keyHint(),
|
||||||
|
new Bounds(bounds.left, bounds.top, width, bounds.height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int normalizedStatusIconWidth(int drawableWidth, int iconHeight) {
|
||||||
|
return Math.max(1, drawableWidth + statusIconHorizontalPadding(iconHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int statusIconHorizontalPadding(int iconHeight) {
|
||||||
|
return Math.max(1, Math.round(Math.max(1, iconHeight) * 0.09f));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int drawableWidth(View view) {
|
||||||
|
Drawable drawable = view instanceof ImageView imageView ? imageView.getDrawable() : null;
|
||||||
|
if (drawable == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int width = drawable.getBounds().width();
|
||||||
|
if (width > 0) {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
return Math.max(0, drawable.getIntrinsicWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int syntheticStatusIconHeight(View view, int fallbackSize) {
|
||||||
|
int height = measuredHeight(view);
|
||||||
|
return height > 0 ? height : Math.max(1, fallbackSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int measuredWidth(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (view.getWidth() > 0) {
|
||||||
|
return view.getWidth();
|
||||||
|
}
|
||||||
|
if (view.getMeasuredWidth() > 0) {
|
||||||
|
return view.getMeasuredWidth();
|
||||||
|
}
|
||||||
|
ViewGroup.LayoutParams lp = view.getLayoutParams();
|
||||||
|
return lp != null && lp.width > 0 ? lp.width : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int measuredHeight(View view) {
|
||||||
|
if (view == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (view.getHeight() > 0) {
|
||||||
|
return view.getHeight();
|
||||||
|
}
|
||||||
|
if (view.getMeasuredHeight() > 0) {
|
||||||
|
return view.getMeasuredHeight();
|
||||||
|
}
|
||||||
|
ViewGroup.LayoutParams lp = view.getLayoutParams();
|
||||||
|
return lp != null && lp.height > 0 ? lp.height : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<View> directChildren(View view) {
|
||||||
|
ArrayList<View> children = new ArrayList<>();
|
||||||
|
if (view instanceof ViewGroup group) {
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
View child = group.getChildAt(i);
|
||||||
|
if (child != null) {
|
||||||
|
children.add(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds representativeStatusIconBounds(
|
||||||
|
View root,
|
||||||
|
View statusIcons,
|
||||||
|
ArrayList<SnapshotSource> sources
|
||||||
|
) {
|
||||||
|
if (sources != null) {
|
||||||
|
for (SnapshotSource source : sources) {
|
||||||
|
if (source == null || !isDescendantOf(source.view(), statusIcons)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Bounds bounds = ViewGeometry.boundsRelativeTo(root, source.view());
|
||||||
|
if (bounds != null && bounds.width > 0 && bounds.height > 0) {
|
||||||
|
int size = Math.max(1, bounds.height);
|
||||||
|
return new Bounds(bounds.left, bounds.top, size, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bounds containerBounds = ViewGeometry.boundsRelativeTo(root, statusIcons);
|
||||||
|
if (containerBounds != null && containerBounds.height > 0) {
|
||||||
|
int size = Math.max(1, containerBounds.height);
|
||||||
|
return new Bounds(containerBounds.left, containerBounds.top, size, size);
|
||||||
|
}
|
||||||
|
return new Bounds(0, 0, 32, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDrawableStatusIconView(View view) {
|
||||||
|
if (view == null || !view.getClass().getName().contains("StatusBarIconView")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Drawable drawable = view instanceof ImageView imageView ? imageView.getDrawable() : null;
|
||||||
|
return drawable != null;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isModernSignalContainer(View view) {
|
private boolean isModernSignalContainer(View view) {
|
||||||
String className = view.getClass().getName();
|
String className = view.getClass().getName();
|
||||||
return className.contains("ModernStatusBarWifiView")
|
return className.contains("ModernStatusBarWifiView")
|
||||||
@@ -304,12 +710,13 @@ final class UnlockedStockSourceCollector {
|
|||||||
while (!queue.isEmpty()) {
|
while (!queue.isEmpty()) {
|
||||||
View view = queue.removeFirst();
|
View view = queue.removeFirst();
|
||||||
if (isStatusChipSnapshotCandidate(root, view)) {
|
if (isStatusChipSnapshotCandidate(root, view)) {
|
||||||
visibleOut.add(new SnapshotSource(view, SnapshotMode.VIEW));
|
SnapshotSource source = statusChipSource(root, view);
|
||||||
metricOut.add(new SnapshotSource(view, SnapshotMode.VIEW));
|
visibleOut.add(source);
|
||||||
|
metricOut.add(source);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (metricOut.isEmpty() && isStatusChipMetricCandidate(root, view)) {
|
if (metricOut.isEmpty() && isStatusChipMetricCandidate(root, view)) {
|
||||||
metricOut.add(new SnapshotSource(view, SnapshotMode.VIEW));
|
metricOut.add(statusChipSource(root, view));
|
||||||
}
|
}
|
||||||
if (view instanceof ViewGroup group) {
|
if (view instanceof ViewGroup group) {
|
||||||
for (int i = 0; i < group.getChildCount(); i++) {
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
@@ -320,9 +727,58 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStatusChipSnapshotCandidate(View root, View view) {
|
private boolean isStatusChipSnapshotCandidate(View root, View view) {
|
||||||
|
return isStatusChipSnapshotCandidate(root, view, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SnapshotSource statusChipSource(View root, View view) {
|
||||||
|
Bounds bounds = ViewGeometry.boundsRelativeTo(root, view);
|
||||||
|
if (bounds == null || bounds.width <= 0 || bounds.height <= 0) {
|
||||||
|
return new SnapshotSource(view, SnapshotMode.STATUS_CHIP);
|
||||||
|
}
|
||||||
|
int measuredWidth = view.getMeasuredWidth();
|
||||||
|
int measuredHeight = view.getMeasuredHeight();
|
||||||
|
if (measuredWidth > bounds.width || measuredHeight > bounds.height) {
|
||||||
|
bounds = new Bounds(
|
||||||
|
bounds.left,
|
||||||
|
bounds.top,
|
||||||
|
Math.max(bounds.width, measuredWidth),
|
||||||
|
Math.max(bounds.height, measuredHeight));
|
||||||
|
}
|
||||||
|
return new SnapshotSource(view, SnapshotMode.STATUS_CHIP, null, bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isKnownStatusChipSnapshotSource(View root, SnapshotSource source) {
|
||||||
|
if (source == null || source.mode() != SnapshotMode.STATUS_CHIP || root == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
View view = source.view();
|
||||||
|
if (view == null
|
||||||
|
|| view == root
|
||||||
|
|| !view.isAttachedToWindow()
|
||||||
|
|| !isDescendantOf(view, root)
|
||||||
|
|| ReflectionSupport.getBooleanField(view, "sbtStatusChipForcedHidden", false)
|
||||||
|
|| !isStatusChipCandidate(view)
|
||||||
|
|| !hasVisibleStatusChipContent(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Bounds bounds = source.boundsOverride() != null
|
||||||
|
? source.boundsOverride()
|
||||||
|
: ViewGeometry.boundsRelativeTo(root, view);
|
||||||
|
return bounds != null
|
||||||
|
&& bounds.width > 0
|
||||||
|
&& bounds.height > 0
|
||||||
|
&& bounds.top >= 0
|
||||||
|
&& bounds.top <= root.getHeight()
|
||||||
|
&& bounds.width < root.getWidth() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStatusChipSnapshotCandidate(View root, View view, boolean allowHidden) {
|
||||||
if (view == null || view == root || view.getVisibility() != View.VISIBLE) {
|
if (view == null || view == root || view.getVisibility() != View.VISIBLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!allowHidden && view.getAlpha() <= 0f && !hasVisibleStatusChipContent(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (ReflectionSupport.getBooleanField(view, "sbtStatusChipForcedHidden", false)) {
|
if (ReflectionSupport.getBooleanField(view, "sbtStatusChipForcedHidden", false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -348,10 +804,46 @@ final class UnlockedStockSourceCollector {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasVisibleStatusChipContent(View source) {
|
||||||
|
if (!(source instanceof ViewGroup group)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ArrayDeque<View> queue = new ArrayDeque<>();
|
||||||
|
for (int i = 0; i < group.getChildCount(); i++) {
|
||||||
|
queue.addLast(group.getChildAt(i));
|
||||||
|
}
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
View view = queue.removeFirst();
|
||||||
|
if (view == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (view.getVisibility() == View.VISIBLE && view.getAlpha() > 0f) {
|
||||||
|
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
||||||
|
int height = view.getHeight() > 0 ? view.getHeight() : view.getMeasuredHeight();
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (view instanceof ViewGroup childGroup) {
|
||||||
|
for (int i = 0; i < childGroup.getChildCount(); i++) {
|
||||||
|
queue.addLast(childGroup.getChildAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isStatusChipMetricCandidate(View root, View view) {
|
private boolean isStatusChipMetricCandidate(View root, View view) {
|
||||||
|
return isStatusChipMetricCandidate(root, view, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStatusChipMetricCandidate(View root, View view, boolean allowHidden) {
|
||||||
if (view == null || view == root || root == null) {
|
if (view == null || view == root || root == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!allowHidden && view.getAlpha() <= 0f && !hasVisibleStatusChipContent(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
||||||
int height = view.getHeight() > 0 ? view.getHeight() : view.getMeasuredHeight();
|
int height = view.getHeight() > 0 ? view.getHeight() : view.getMeasuredHeight();
|
||||||
if (width <= 0 || height <= 0 || width >= root.getWidth() / 2) {
|
if (width <= 0 || height <= 0 || width >= root.getWidth() / 2) {
|
||||||
@@ -386,7 +878,14 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStatusSnapshotCandidate(View view) {
|
private boolean isStatusSnapshotCandidate(View view) {
|
||||||
if (view.getVisibility() != View.VISIBLE) {
|
return isStatusSnapshotCandidate(view, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isStatusSnapshotCandidate(View view, boolean includeHidden) {
|
||||||
|
if (isOwnedRuntimeView(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!includeHidden && view.getVisibility() != View.VISIBLE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
int width = view.getWidth() > 0 ? view.getWidth() : view.getMeasuredWidth();
|
||||||
@@ -424,6 +923,9 @@ final class UnlockedStockSourceCollector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isNotificationSnapshotCandidate(View view) {
|
private boolean isNotificationSnapshotCandidate(View view) {
|
||||||
|
if (isOwnedRuntimeView(view)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (view instanceof TextView) {
|
if (view instanceof TextView) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -466,6 +968,19 @@ final class UnlockedStockSourceCollector {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isOwnedRuntimeView(View view) {
|
||||||
|
View current = view;
|
||||||
|
while (current != null) {
|
||||||
|
Object tag = current.getTag();
|
||||||
|
if (tag instanceof String value && value.startsWith("statusbartweak.")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Object parent = current.getParent();
|
||||||
|
current = parent instanceof View ? (View) parent : null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private static int viewSignatureOrZero(View view) {
|
private static int viewSignatureOrZero(View view) {
|
||||||
return view != null ? viewSignature(view) : 0;
|
return view != null ? viewSignature(view) : 0;
|
||||||
}
|
}
|
||||||
@@ -571,9 +1086,6 @@ final class UnlockedStockSourceCollector {
|
|||||||
hasKnownChipSource = true;
|
hasKnownChipSource = true;
|
||||||
result = 31 * result + chipSourceListSignature(previousIcons.statusChipMetrics);
|
result = 31 * result + chipSourceListSignature(previousIcons.statusChipMetrics);
|
||||||
}
|
}
|
||||||
if (!hasKnownChipSource) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!hasKnownChipSource) {
|
if (!hasKnownChipSource) {
|
||||||
result = 31 * result + statusChipCandidateSignature(root);
|
result = 31 * result + statusChipCandidateSignature(root);
|
||||||
@@ -590,7 +1102,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
queue.add(root);
|
queue.add(root);
|
||||||
while (!queue.isEmpty()) {
|
while (!queue.isEmpty()) {
|
||||||
View view = queue.removeFirst();
|
View view = queue.removeFirst();
|
||||||
if (view != root && isStatusChipCandidate(view)) {
|
if (view != root && isStatusChipCandidate(view) && hasVisibleStatusChipContent(view)) {
|
||||||
result = 31 * result + chipViewLayoutSignature(view);
|
result = 31 * result + chipViewLayoutSignature(view);
|
||||||
}
|
}
|
||||||
if (view instanceof ViewGroup group) {
|
if (view instanceof ViewGroup group) {
|
||||||
@@ -602,7 +1114,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int chipSourceListSignature(ArrayList<SnapshotSource> sources) {
|
private int chipSourceListSignature(ArrayList<SnapshotSource> sources) {
|
||||||
if (sources == null || sources.isEmpty()) {
|
if (sources == null || sources.isEmpty()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -610,6 +1122,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
result = 31 * result + sources.size();
|
result = 31 * result + sources.size();
|
||||||
for (SnapshotSource source : sources) {
|
for (SnapshotSource source : sources) {
|
||||||
result = 31 * result + source.mode().ordinal();
|
result = 31 * result + source.mode().ordinal();
|
||||||
|
result = 31 * result + (hasVisibleStatusChipContent(source.view()) ? 1 : 0);
|
||||||
result = 31 * result + chipViewLayoutSignature(source.view());
|
result = 31 * result + chipViewLayoutSignature(source.view());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -679,6 +1192,18 @@ final class UnlockedStockSourceCollector {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int boundsSignature(Bounds bounds) {
|
||||||
|
if (bounds == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int result = 17;
|
||||||
|
result = 31 * result + bounds.left;
|
||||||
|
result = 31 * result + bounds.top;
|
||||||
|
result = 31 * result + bounds.width;
|
||||||
|
result = 31 * result + bounds.height;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private static int drawableLayoutSignature(android.graphics.drawable.Drawable drawable) {
|
private static int drawableLayoutSignature(android.graphics.drawable.Drawable drawable) {
|
||||||
if (drawable == null) {
|
if (drawable == null) {
|
||||||
return 0;
|
return 0;
|
||||||
@@ -761,6 +1286,7 @@ final class UnlockedStockSourceCollector {
|
|||||||
settings.layoutChipMiddleSide,
|
settings.layoutChipMiddleSide,
|
||||||
settings.layoutChipMiddleAutoNearestSide,
|
settings.layoutChipMiddleAutoNearestSide,
|
||||||
settings.layoutChipVerticalOffsetPx,
|
settings.layoutChipVerticalOffsetPx,
|
||||||
|
settings.layoutChipHeightSteps,
|
||||||
settings.layoutNotifPosition,
|
settings.layoutNotifPosition,
|
||||||
settings.layoutNotifSortOrder,
|
settings.layoutNotifSortOrder,
|
||||||
settings.layoutNotifEnabledUnlocked,
|
settings.layoutNotifEnabledUnlocked,
|
||||||
@@ -775,6 +1301,12 @@ final class UnlockedStockSourceCollector {
|
|||||||
java.util.Arrays.hashCode(settings.layoutNotifLockMiddleSides),
|
java.util.Arrays.hashCode(settings.layoutNotifLockMiddleSides),
|
||||||
java.util.Arrays.hashCode(settings.layoutNotifLockMiddleAutoNearestSides),
|
java.util.Arrays.hashCode(settings.layoutNotifLockMiddleAutoNearestSides),
|
||||||
java.util.Arrays.hashCode(settings.layoutNotifLockVerticalOffsetsPx),
|
java.util.Arrays.hashCode(settings.layoutNotifLockVerticalOffsetsPx),
|
||||||
|
settings.layoutNotifEnabledAod,
|
||||||
|
settings.layoutNotifAodCount,
|
||||||
|
java.util.Arrays.hashCode(settings.layoutNotifAodPositions),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutNotifAodMiddleSides),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutNotifAodMiddleAutoNearestSides),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutNotifAodVerticalOffsetsPx),
|
||||||
settings.layoutNotifMiddleSide,
|
settings.layoutNotifMiddleSide,
|
||||||
settings.layoutNotifMiddleAutoNearestSide,
|
settings.layoutNotifMiddleAutoNearestSide,
|
||||||
settings.layoutNotifVerticalOffsetPx,
|
settings.layoutNotifVerticalOffsetPx,
|
||||||
@@ -791,6 +1323,12 @@ final class UnlockedStockSourceCollector {
|
|||||||
java.util.Arrays.hashCode(settings.layoutStatusLockMiddleSides),
|
java.util.Arrays.hashCode(settings.layoutStatusLockMiddleSides),
|
||||||
java.util.Arrays.hashCode(settings.layoutStatusLockMiddleAutoNearestSides),
|
java.util.Arrays.hashCode(settings.layoutStatusLockMiddleAutoNearestSides),
|
||||||
java.util.Arrays.hashCode(settings.layoutStatusLockVerticalOffsetsPx),
|
java.util.Arrays.hashCode(settings.layoutStatusLockVerticalOffsetsPx),
|
||||||
|
settings.layoutStatusEnabledAod,
|
||||||
|
settings.layoutStatusAodCount,
|
||||||
|
java.util.Arrays.hashCode(settings.layoutStatusAodPositions),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutStatusAodMiddleSides),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutStatusAodMiddleAutoNearestSides),
|
||||||
|
java.util.Arrays.hashCode(settings.layoutStatusAodVerticalOffsetsPx),
|
||||||
settings.layoutStatusMiddleSide,
|
settings.layoutStatusMiddleSide,
|
||||||
settings.layoutStatusMiddleAutoNearestSide,
|
settings.layoutStatusMiddleAutoNearestSide,
|
||||||
settings.layoutStatusVerticalOffsetPx,
|
settings.layoutStatusVerticalOffsetPx,
|
||||||
@@ -802,4 +1340,12 @@ final class UnlockedStockSourceCollector {
|
|||||||
settings.statusChipsHideNavUnlocked,
|
settings.statusChipsHideNavUnlocked,
|
||||||
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-6
@@ -5,7 +5,6 @@ import android.widget.TextView;
|
|||||||
final class UnlockedVerticalOffsetScaler {
|
final class UnlockedVerticalOffsetScaler {
|
||||||
private int baselineNotificationIconSizePx;
|
private int baselineNotificationIconSizePx;
|
||||||
private int baselineStatusIconHeightPx;
|
private int baselineStatusIconHeightPx;
|
||||||
private int baselineChipHeightPx;
|
|
||||||
private float baselineClockTextSizePx;
|
private float baselineClockTextSizePx;
|
||||||
|
|
||||||
int notification(int offsetPx, int currentIconHeightPx) {
|
int notification(int offsetPx, int currentIconHeightPx) {
|
||||||
@@ -22,11 +21,6 @@ final class UnlockedVerticalOffsetScaler {
|
|||||||
return scaledOffset(offsetPx, currentIconHeightPx, baselineStatusIconHeightPx);
|
return scaledOffset(offsetPx, currentIconHeightPx, baselineStatusIconHeightPx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int chip(int offsetPx, int currentChipHeightPx) {
|
|
||||||
baselineChipHeightPx = updateBaseline(baselineChipHeightPx, currentChipHeightPx);
|
|
||||||
return scaledOffset(offsetPx, currentChipHeightPx, baselineChipHeightPx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int clock(int offsetPx, TextView source) {
|
int clock(int offsetPx, TextView source) {
|
||||||
if (offsetPx == 0 || source == null || source.getTextSize() <= 0f) {
|
if (offsetPx == 0 || source == null || source.getTextSize() <= 0f) {
|
||||||
return offsetPx;
|
return offsetPx;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class AppIconRules {
|
public final class AppIconRules {
|
||||||
@@ -24,6 +25,9 @@ public final class AppIconRules {
|
|||||||
|
|
||||||
public static final String EXTRA_PACKAGE = "package";
|
public static final String EXTRA_PACKAGE = "package";
|
||||||
public static final String EXTRA_FIRST_SEEN_MS = "first_seen_ms";
|
public static final String EXTRA_FIRST_SEEN_MS = "first_seen_ms";
|
||||||
|
public static final String EXTRA_LAST_SEEN_MS = "last_seen_ms";
|
||||||
|
public static final String EXTRA_LAST_SEEN_TIMEZONE_OFFSET_MINUTES =
|
||||||
|
"last_seen_timezone_offset_minutes";
|
||||||
|
|
||||||
public static final int MODE_AOD = 1;
|
public static final int MODE_AOD = 1;
|
||||||
public static final int MODE_LOCK = 1 << 1;
|
public static final int MODE_LOCK = 1 << 1;
|
||||||
@@ -73,7 +77,7 @@ public final class AppIconRules {
|
|||||||
prefs.edit().putStringSet(PREF_KEY_BLOCKED_MODES, encoded).apply();
|
prefs.edit().putStringSet(PREF_KEY_BLOCKED_MODES, encoded).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Long> loadSeenSession(SharedPreferences prefs) {
|
public static Map<String, SeenApp> loadSeenSession(SharedPreferences prefs) {
|
||||||
if (prefs == null) {
|
if (prefs == null) {
|
||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
@@ -97,7 +101,7 @@ public final class AppIconRules {
|
|||||||
prefs.edit().putStringSet(PREF_KEY_EXCEPTION_RULES, encoded).apply();
|
prefs.edit().putStringSet(PREF_KEY_EXCEPTION_RULES, encoded).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void saveSeenSession(SharedPreferences prefs, Map<String, Long> map) {
|
public static void saveSeenSession(SharedPreferences prefs, Map<String, SeenApp> map) {
|
||||||
if (prefs == null) {
|
if (prefs == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -112,18 +116,37 @@ public final class AppIconRules {
|
|||||||
prefs.edit().remove(PREF_KEY_SEEN_SESSION).apply();
|
prefs.edit().remove(PREF_KEY_SEEN_SESSION).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void noteSeen(Map<String, Long> seen, String pkg, long firstSeenMs) {
|
public static boolean noteSeen(Map<String, SeenApp> seen,
|
||||||
|
String pkg,
|
||||||
|
long seenMs,
|
||||||
|
int timezoneOffsetMinutes) {
|
||||||
if (seen == null || !isValidPackageName(pkg)) {
|
if (seen == null || !isValidPackageName(pkg)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
Long existing = seen.get(pkg);
|
if (seenMs <= 0L) {
|
||||||
|
seenMs = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
SeenApp existing = seen.get(pkg);
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
seen.put(pkg, firstSeenMs);
|
seen.put(pkg, new SeenApp(pkg, seenMs, seenMs, timezoneOffsetMinutes));
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
if (firstSeenMs > 0 && firstSeenMs < existing) {
|
long firstSeenMs = existing.firstSeenMs > 0L
|
||||||
seen.put(pkg, firstSeenMs);
|
? Math.min(existing.firstSeenMs, seenMs)
|
||||||
|
: seenMs;
|
||||||
|
long lastSeenMs = existing.lastSeenMs;
|
||||||
|
int lastSeenOffsetMinutes = existing.lastSeenTimezoneOffsetMinutes;
|
||||||
|
if (lastSeenMs <= 0L || seenMs >= lastSeenMs) {
|
||||||
|
lastSeenMs = seenMs;
|
||||||
|
lastSeenOffsetMinutes = timezoneOffsetMinutes;
|
||||||
}
|
}
|
||||||
|
if (firstSeenMs == existing.firstSeenMs
|
||||||
|
&& lastSeenMs == existing.lastSeenMs
|
||||||
|
&& lastSeenOffsetMinutes == existing.lastSeenTimezoneOffsetMinutes) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seen.put(pkg, new SeenApp(pkg, firstSeenMs, lastSeenMs, lastSeenOffsetMinutes));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isBlocked(Map<String, Integer> masks, String pkg, String mode) {
|
public static boolean isBlocked(Map<String, Integer> masks, String pkg, String mode) {
|
||||||
@@ -367,8 +390,8 @@ public final class AppIconRules {
|
|||||||
return MODE_NAME_UNKNOWN;
|
return MODE_NAME_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, Long> parseSeenSession(Set<String> rawSet) {
|
public static Map<String, SeenApp> parseSeenSession(Set<String> rawSet) {
|
||||||
Map<String, Long> out = new HashMap<>();
|
Map<String, SeenApp> out = new HashMap<>();
|
||||||
if (rawSet == null || rawSet.isEmpty()) {
|
if (rawSet == null || rawSet.isEmpty()) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -377,7 +400,7 @@ public final class AppIconRules {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String[] parts = entry.split("\\|", -1);
|
String[] parts = entry.split("\\|", -1);
|
||||||
if (parts.length != 2) {
|
if (parts.length != 2 && parts.length != 4) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String pkg = parts[0];
|
String pkg = parts[0];
|
||||||
@@ -385,38 +408,61 @@ public final class AppIconRules {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long firstSeen;
|
long firstSeen;
|
||||||
|
long lastSeen;
|
||||||
|
int lastSeenOffsetMinutes;
|
||||||
try {
|
try {
|
||||||
firstSeen = Long.parseLong(parts[1]);
|
firstSeen = Long.parseLong(parts[1]);
|
||||||
|
if (parts.length == 4) {
|
||||||
|
lastSeen = Long.parseLong(parts[2]);
|
||||||
|
lastSeenOffsetMinutes = Integer.parseInt(parts[3]);
|
||||||
|
} else {
|
||||||
|
lastSeen = firstSeen;
|
||||||
|
lastSeenOffsetMinutes = currentTimezoneOffsetMinutes();
|
||||||
|
}
|
||||||
} catch (NumberFormatException ignored) {
|
} catch (NumberFormatException ignored) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (firstSeen <= 0L) {
|
if (firstSeen <= 0L || lastSeen <= 0L) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Long existing = out.get(pkg);
|
SeenApp existing = out.get(pkg);
|
||||||
if (existing == null || firstSeen < existing) {
|
if (existing == null) {
|
||||||
out.put(pkg, firstSeen);
|
out.put(pkg, new SeenApp(pkg, firstSeen, lastSeen, lastSeenOffsetMinutes));
|
||||||
|
} else {
|
||||||
|
long mergedFirstSeen = Math.min(existing.firstSeenMs, firstSeen);
|
||||||
|
long mergedLastSeen = existing.lastSeenMs;
|
||||||
|
int mergedOffset = existing.lastSeenTimezoneOffsetMinutes;
|
||||||
|
if (lastSeen >= mergedLastSeen) {
|
||||||
|
mergedLastSeen = lastSeen;
|
||||||
|
mergedOffset = lastSeenOffsetMinutes;
|
||||||
|
}
|
||||||
|
out.put(pkg, new SeenApp(pkg, mergedFirstSeen, mergedLastSeen, mergedOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Set<String> encodeSeenSession(Map<String, Long> map) {
|
public static Set<String> encodeSeenSession(Map<String, SeenApp> map) {
|
||||||
Set<String> out = new HashSet<>();
|
Set<String> out = new HashSet<>();
|
||||||
if (map == null || map.isEmpty()) {
|
if (map == null || map.isEmpty()) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, Long> e : map.entrySet()) {
|
for (Map.Entry<String, SeenApp> e : map.entrySet()) {
|
||||||
String pkg = e.getKey();
|
String pkg = e.getKey();
|
||||||
Long firstSeenObj = e.getValue();
|
SeenApp app = e.getValue();
|
||||||
if (!isValidPackageName(pkg) || firstSeenObj == null) {
|
if (!isValidPackageName(pkg) || app == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
long firstSeen = firstSeenObj;
|
long firstSeen = app.firstSeenMs;
|
||||||
|
long lastSeen = app.lastSeenMs;
|
||||||
if (firstSeen <= 0L) {
|
if (firstSeen <= 0L) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out.add(pkg + "|" + firstSeen);
|
if (lastSeen <= 0L) {
|
||||||
|
lastSeen = firstSeen;
|
||||||
|
}
|
||||||
|
out.add(pkg + "|" + firstSeen + "|" + lastSeen + "|"
|
||||||
|
+ app.lastSeenTimezoneOffsetMinutes);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -424,10 +470,17 @@ public final class AppIconRules {
|
|||||||
public static final class SeenApp {
|
public static final class SeenApp {
|
||||||
public final String packageName;
|
public final String packageName;
|
||||||
public final long firstSeenMs;
|
public final long firstSeenMs;
|
||||||
|
public final long lastSeenMs;
|
||||||
|
public final int lastSeenTimezoneOffsetMinutes;
|
||||||
|
|
||||||
public SeenApp(String packageName, long firstSeenMs) {
|
public SeenApp(String packageName,
|
||||||
|
long firstSeenMs,
|
||||||
|
long lastSeenMs,
|
||||||
|
int lastSeenTimezoneOffsetMinutes) {
|
||||||
this.packageName = packageName;
|
this.packageName = packageName;
|
||||||
this.firstSeenMs = firstSeenMs;
|
this.firstSeenMs = firstSeenMs;
|
||||||
|
this.lastSeenMs = lastSeenMs;
|
||||||
|
this.lastSeenTimezoneOffsetMinutes = lastSeenTimezoneOffsetMinutes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -459,18 +512,23 @@ public final class AppIconRules {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<SeenApp> sortSeenOldestFirst(Map<String, Long> seen) {
|
public static int currentTimezoneOffsetMinutes() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
return TimeZone.getDefault().getOffset(now) / 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<SeenApp> sortSeenOldestFirst(Map<String, SeenApp> seen) {
|
||||||
List<SeenApp> out = new ArrayList<>();
|
List<SeenApp> out = new ArrayList<>();
|
||||||
if (seen == null || seen.isEmpty()) {
|
if (seen == null || seen.isEmpty()) {
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, Long> e : seen.entrySet()) {
|
for (Map.Entry<String, SeenApp> e : seen.entrySet()) {
|
||||||
String pkg = e.getKey();
|
String pkg = e.getKey();
|
||||||
Long firstSeen = e.getValue();
|
SeenApp app = e.getValue();
|
||||||
if (!isValidPackageName(pkg) || firstSeen == null || firstSeen <= 0L) {
|
if (!isValidPackageName(pkg) || app == null || app.firstSeenMs <= 0L) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out.add(new SeenApp(pkg, firstSeen));
|
out.add(app);
|
||||||
}
|
}
|
||||||
out.sort((a, b) -> Long.compare(a.firstSeenMs, b.firstSeenMs));
|
out.sort((a, b) -> Long.compare(a.firstSeenMs, b.firstSeenMs));
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ public final class SbtDefaults {
|
|||||||
public static final boolean DEBUG_VISUALIZE_CLOCK_CONTAINER_DEFAULT = false;
|
public static final boolean DEBUG_VISUALIZE_CLOCK_CONTAINER_DEFAULT = false;
|
||||||
public static final boolean DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT = false;
|
public static final boolean DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT = false;
|
||||||
public static final boolean DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT = false;
|
public static final boolean DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT = false;
|
||||||
|
public static final boolean DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT = false;
|
||||||
|
|
||||||
public static final int LAYOUT_PADDING_CUTOUT_PX_DEFAULT = 0;
|
public static final int LAYOUT_PADDING_CUTOUT_PX_DEFAULT = 0;
|
||||||
public static final int LAYOUT_PADDING_LEFT_PX_DEFAULT = 0;
|
public static final int LAYOUT_PADDING_LEFT_PX_DEFAULT = 0;
|
||||||
@@ -114,6 +115,7 @@ public final class SbtDefaults {
|
|||||||
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 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 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_SHOW_DOT_IF_TRUNCATED_DEFAULT = true;
|
||||||
@@ -124,6 +126,11 @@ public final class SbtDefaults {
|
|||||||
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 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_LOCK_ICON_HEIGHT_STEPS_DEFAULT = 46;
|
||||||
|
public static final int LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT = 46;
|
||||||
|
public static final int LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT = 59;
|
||||||
|
public static final int LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT = 65;
|
||||||
public static final String LAYOUT_STATUS_POSITION_DEFAULT = "right";
|
public static final String LAYOUT_STATUS_POSITION_DEFAULT = "right";
|
||||||
public static final boolean LAYOUT_STATUS_ENABLED_AOD_DEFAULT = true;
|
public static final boolean LAYOUT_STATUS_ENABLED_AOD_DEFAULT = true;
|
||||||
public static final boolean LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT = true;
|
public static final boolean LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT = true;
|
||||||
@@ -133,6 +140,9 @@ public final class SbtDefaults {
|
|||||||
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 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_ICON_HEIGHT_STEPS_MIN = 10;
|
||||||
|
public static final int LAYOUT_ICON_HEIGHT_STEPS_MAX = 100;
|
||||||
public static final int LAYOUT_ICON_CONTAINER_COUNT_MIN = 0;
|
public static final int LAYOUT_ICON_CONTAINER_COUNT_MIN = 0;
|
||||||
public static final int LAYOUT_ICON_CONTAINER_COUNT_MAX = 3;
|
public static final int LAYOUT_ICON_CONTAINER_COUNT_MAX = 3;
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ public final class SbtSettings {
|
|||||||
"debug_visualize_chip_container";
|
"debug_visualize_chip_container";
|
||||||
public static final String KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT =
|
public static final String KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT =
|
||||||
"debug_visualize_camera_cutout";
|
"debug_visualize_camera_cutout";
|
||||||
|
public static final String KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS =
|
||||||
|
"debug_visualize_aod_stock_containers";
|
||||||
public static final String KEY_LOCKED_NOTIFICATION_MODE =
|
public static final String KEY_LOCKED_NOTIFICATION_MODE =
|
||||||
"locked_notification_mode";
|
"locked_notification_mode";
|
||||||
public static final String KEY_UNLOCKED_MAX_ICONS_PER_ROW = "unlocked_max_icons_per_row";
|
public static final String KEY_UNLOCKED_MAX_ICONS_PER_ROW = "unlocked_max_icons_per_row";
|
||||||
@@ -50,10 +52,12 @@ public final class SbtSettings {
|
|||||||
public static final String KEY_CARDS_AOD_MAX_ROWS = "cards_aod_max_rows";
|
public static final String KEY_CARDS_AOD_MAX_ROWS = "cards_aod_max_rows";
|
||||||
public static final String KEY_CARDS_AOD_EVEN_DISTRIBUTION = "cards_aod_even_distribution";
|
public static final String KEY_CARDS_AOD_EVEN_DISTRIBUTION = "cards_aod_even_distribution";
|
||||||
public static final String KEY_CARDS_AOD_LIMIT_TO_WIDTH = "cards_aod_limit_to_width";
|
public static final String KEY_CARDS_AOD_LIMIT_TO_WIDTH = "cards_aod_limit_to_width";
|
||||||
|
public static final String KEY_CARDS_AOD_ICON_HEIGHT_STEPS = "cards_aod_icon_height_steps";
|
||||||
public static final String KEY_CARDS_LOCK_MAX_ICONS_PER_ROW = "cards_lock_max_icons_per_row";
|
public static final String KEY_CARDS_LOCK_MAX_ICONS_PER_ROW = "cards_lock_max_icons_per_row";
|
||||||
public static final String KEY_CARDS_LOCK_MAX_ROWS = "cards_lock_max_rows";
|
public static final String KEY_CARDS_LOCK_MAX_ROWS = "cards_lock_max_rows";
|
||||||
public static final String KEY_CARDS_LOCK_EVEN_DISTRIBUTION = "cards_lock_even_distribution";
|
public static final String KEY_CARDS_LOCK_EVEN_DISTRIBUTION = "cards_lock_even_distribution";
|
||||||
public static final String KEY_CARDS_LOCK_LIMIT_TO_WIDTH = "cards_lock_limit_to_width";
|
public static final String KEY_CARDS_LOCK_LIMIT_TO_WIDTH = "cards_lock_limit_to_width";
|
||||||
|
public static final String KEY_CARDS_LOCK_ICON_HEIGHT_STEPS = "cards_lock_icon_height_steps";
|
||||||
public static final String KEY_STATUS_CHIPS_HIDE_ALL = "status_chips_hide_all";
|
public static final String KEY_STATUS_CHIPS_HIDE_ALL = "status_chips_hide_all";
|
||||||
public static final String KEY_STATUS_CHIPS_HIDE_MEDIA_UNLOCKED = "status_chips_hide_media_unlocked";
|
public static final String KEY_STATUS_CHIPS_HIDE_MEDIA_UNLOCKED = "status_chips_hide_media_unlocked";
|
||||||
public static final String KEY_STATUS_CHIPS_HIDE_NAV_UNLOCKED = "status_chips_hide_nav_unlocked";
|
public static final String KEY_STATUS_CHIPS_HIDE_NAV_UNLOCKED = "status_chips_hide_nav_unlocked";
|
||||||
@@ -105,6 +109,7 @@ public final class SbtSettings {
|
|||||||
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_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_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_SHOW_DOT_IF_TRUNCATED = "layout_notif_show_dot_if_truncated";
|
||||||
@@ -115,6 +120,7 @@ public final class SbtSettings {
|
|||||||
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_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_STATUS_POSITION = "layout_status_position";
|
public static final String KEY_LAYOUT_STATUS_POSITION = "layout_status_position";
|
||||||
public static final String KEY_LAYOUT_STATUS_ENABLED_AOD = "layout_status_enabled_aod";
|
public static final String KEY_LAYOUT_STATUS_ENABLED_AOD = "layout_status_enabled_aod";
|
||||||
public static final String KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN = "layout_status_enabled_lockscreen";
|
public static final String KEY_LAYOUT_STATUS_ENABLED_LOCKSCREEN = "layout_status_enabled_lockscreen";
|
||||||
@@ -124,6 +130,7 @@ public final class SbtSettings {
|
|||||||
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_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_SYSTEM_ICON_BLOCKED_MODES = SystemIconRules.PREF_KEY_BLOCKED_MODES;
|
public static final String KEY_SYSTEM_ICON_BLOCKED_MODES = SystemIconRules.PREF_KEY_BLOCKED_MODES;
|
||||||
public static final String KEY_SYSTEM_ICON_HIDE_SLOTS = "system_icon_hide_slots";
|
public static final String KEY_SYSTEM_ICON_HIDE_SLOTS = "system_icon_hide_slots";
|
||||||
public static final String KEY_APP_ICON_BLOCKED_MODES = AppIconRules.PREF_KEY_BLOCKED_MODES;
|
public static final String KEY_APP_ICON_BLOCKED_MODES = AppIconRules.PREF_KEY_BLOCKED_MODES;
|
||||||
@@ -177,6 +184,30 @@ public final class SbtSettings {
|
|||||||
return suffixedKey("layout_lock_notifications_vertical_offset_px", index);
|
return suffixedKey("layout_lock_notifications_vertical_offset_px", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String layoutLockNotifIconHeightKey() {
|
||||||
|
return "layout_lock_notifications_icon_height_steps";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodNotifPositionKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_notifications_position", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodNotifMiddleSideKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_notifications_middle_side", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodNotifMiddleAutoNearestSideKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_notifications_middle_auto_nearest_side", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodNotifVerticalOffsetKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_notifications_vertical_offset_px", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodNotifIconHeightKey() {
|
||||||
|
return "layout_aod_notifications_icon_height_steps";
|
||||||
|
}
|
||||||
|
|
||||||
public static String layoutLockStatusPositionKey(int index) {
|
public static String layoutLockStatusPositionKey(int index) {
|
||||||
return suffixedKey("layout_lock_status_position", index);
|
return suffixedKey("layout_lock_status_position", index);
|
||||||
}
|
}
|
||||||
@@ -193,6 +224,30 @@ public final class SbtSettings {
|
|||||||
return suffixedKey("layout_lock_status_vertical_offset_px", index);
|
return suffixedKey("layout_lock_status_vertical_offset_px", index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String layoutLockStatusIconHeightKey() {
|
||||||
|
return "layout_lock_status_icon_height_steps";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodStatusPositionKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_status_position", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodStatusMiddleSideKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_status_middle_side", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodStatusMiddleAutoNearestSideKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_status_middle_auto_nearest_side", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodStatusVerticalOffsetKey(int index) {
|
||||||
|
return suffixedKey("layout_aod_status_vertical_offset_px", index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String layoutAodStatusIconHeightKey() {
|
||||||
|
return "layout_aod_status_icon_height_steps";
|
||||||
|
}
|
||||||
|
|
||||||
private static String suffixedKey(String base, int index) {
|
private static String suffixedKey(String base, int index) {
|
||||||
return index <= 0 ? base : base + "_" + (index + 1);
|
return index <= 0 ? base : base + "_" + (index + 1);
|
||||||
}
|
}
|
||||||
@@ -209,10 +264,12 @@ public final class SbtSettings {
|
|||||||
public final int cardsAodMaxRows;
|
public final int cardsAodMaxRows;
|
||||||
public final boolean cardsAodEvenDistribution;
|
public final boolean cardsAodEvenDistribution;
|
||||||
public final boolean cardsAodLimitToWidth;
|
public final boolean cardsAodLimitToWidth;
|
||||||
|
public final int cardsAodIconHeightSteps;
|
||||||
public final int cardsLockMaxIconsPerRow;
|
public final int cardsLockMaxIconsPerRow;
|
||||||
public final int cardsLockMaxRows;
|
public final int cardsLockMaxRows;
|
||||||
public final boolean cardsLockEvenDistribution;
|
public final boolean cardsLockEvenDistribution;
|
||||||
public final boolean cardsLockLimitToWidth;
|
public final boolean cardsLockLimitToWidth;
|
||||||
|
public final int cardsLockIconHeightSteps;
|
||||||
public final boolean keepAodVisibleDuringCall;
|
public final boolean keepAodVisibleDuringCall;
|
||||||
public final boolean batteryLockscreenUnpluggedPercent;
|
public final boolean batteryLockscreenUnpluggedPercent;
|
||||||
public final boolean batteryAodUnpluggedPercent;
|
public final boolean batteryAodUnpluggedPercent;
|
||||||
@@ -259,6 +316,7 @@ public final class SbtSettings {
|
|||||||
public final String layoutChipMiddleSide;
|
public final String layoutChipMiddleSide;
|
||||||
public final boolean layoutChipMiddleAutoNearestSide;
|
public final boolean layoutChipMiddleAutoNearestSide;
|
||||||
public final int layoutChipVerticalOffsetPx;
|
public final int layoutChipVerticalOffsetPx;
|
||||||
|
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 layoutNotifShowDotIfTruncated;
|
||||||
@@ -275,9 +333,17 @@ public final class SbtSettings {
|
|||||||
public final String[] layoutNotifLockMiddleSides;
|
public final String[] layoutNotifLockMiddleSides;
|
||||||
public final boolean[] layoutNotifLockMiddleAutoNearestSides;
|
public final boolean[] layoutNotifLockMiddleAutoNearestSides;
|
||||||
public final int[] layoutNotifLockVerticalOffsetsPx;
|
public final int[] layoutNotifLockVerticalOffsetsPx;
|
||||||
|
public final int layoutNotifAodCount;
|
||||||
|
public final String[] layoutNotifAodPositions;
|
||||||
|
public final String[] layoutNotifAodMiddleSides;
|
||||||
|
public final boolean[] layoutNotifAodMiddleAutoNearestSides;
|
||||||
|
public final int[] layoutNotifAodVerticalOffsetsPx;
|
||||||
public final String layoutNotifMiddleSide;
|
public final String layoutNotifMiddleSide;
|
||||||
public final boolean layoutNotifMiddleAutoNearestSide;
|
public final boolean layoutNotifMiddleAutoNearestSide;
|
||||||
public final int layoutNotifVerticalOffsetPx;
|
public final int layoutNotifVerticalOffsetPx;
|
||||||
|
public final int layoutNotifIconHeightSteps;
|
||||||
|
public final int layoutNotifLockIconHeightSteps;
|
||||||
|
public final int layoutNotifAodIconHeightSteps;
|
||||||
public final String layoutStatusPosition;
|
public final String layoutStatusPosition;
|
||||||
public final boolean layoutStatusEnabledAod;
|
public final boolean layoutStatusEnabledAod;
|
||||||
public final boolean layoutStatusEnabledLockscreen;
|
public final boolean layoutStatusEnabledLockscreen;
|
||||||
@@ -292,10 +358,18 @@ public final class SbtSettings {
|
|||||||
public final String[] layoutStatusLockMiddleSides;
|
public final String[] layoutStatusLockMiddleSides;
|
||||||
public final boolean[] layoutStatusLockMiddleAutoNearestSides;
|
public final boolean[] layoutStatusLockMiddleAutoNearestSides;
|
||||||
public final int[] layoutStatusLockVerticalOffsetsPx;
|
public final int[] layoutStatusLockVerticalOffsetsPx;
|
||||||
|
public final int layoutStatusAodCount;
|
||||||
|
public final String[] layoutStatusAodPositions;
|
||||||
|
public final String[] layoutStatusAodMiddleSides;
|
||||||
|
public final boolean[] layoutStatusAodMiddleAutoNearestSides;
|
||||||
|
public final int[] layoutStatusAodVerticalOffsetsPx;
|
||||||
public final boolean layoutStatusShowDotIfTruncated;
|
public final boolean layoutStatusShowDotIfTruncated;
|
||||||
public final String layoutStatusMiddleSide;
|
public final String layoutStatusMiddleSide;
|
||||||
public final boolean layoutStatusMiddleAutoNearestSide;
|
public final boolean layoutStatusMiddleAutoNearestSide;
|
||||||
public final int layoutStatusVerticalOffsetPx;
|
public final int layoutStatusVerticalOffsetPx;
|
||||||
|
public final int layoutStatusIconHeightSteps;
|
||||||
|
public final int layoutStatusLockIconHeightSteps;
|
||||||
|
public final int layoutStatusAodIconHeightSteps;
|
||||||
public final Map<String, String> clockCameraTypeOverrides;
|
public final Map<String, String> clockCameraTypeOverrides;
|
||||||
public final Map<String, Integer> systemIconBlockedModes;
|
public final Map<String, Integer> systemIconBlockedModes;
|
||||||
public final boolean statusChipsHideAll;
|
public final boolean statusChipsHideAll;
|
||||||
@@ -310,6 +384,7 @@ public final class SbtSettings {
|
|||||||
public final boolean debugVisualizeClockContainer;
|
public final boolean debugVisualizeClockContainer;
|
||||||
public final boolean debugVisualizeChipContainer;
|
public final boolean debugVisualizeChipContainer;
|
||||||
public final boolean debugVisualizeCameraCutout;
|
public final boolean debugVisualizeCameraCutout;
|
||||||
|
public final boolean debugVisualizeAodStockContainers;
|
||||||
|
|
||||||
private SbtSettings(boolean enableAodCutoutLimit,
|
private SbtSettings(boolean enableAodCutoutLimit,
|
||||||
boolean enableLockCutoutLimit,
|
boolean enableLockCutoutLimit,
|
||||||
@@ -324,10 +399,12 @@ public final class SbtSettings {
|
|||||||
int cardsAodMaxRows,
|
int cardsAodMaxRows,
|
||||||
boolean cardsAodEvenDistribution,
|
boolean cardsAodEvenDistribution,
|
||||||
boolean cardsAodLimitToWidth,
|
boolean cardsAodLimitToWidth,
|
||||||
|
int cardsAodIconHeightSteps,
|
||||||
int cardsLockMaxIconsPerRow,
|
int cardsLockMaxIconsPerRow,
|
||||||
int cardsLockMaxRows,
|
int cardsLockMaxRows,
|
||||||
boolean cardsLockEvenDistribution,
|
boolean cardsLockEvenDistribution,
|
||||||
boolean cardsLockLimitToWidth,
|
boolean cardsLockLimitToWidth,
|
||||||
|
int cardsLockIconHeightSteps,
|
||||||
boolean keepAodVisibleDuringCall,
|
boolean keepAodVisibleDuringCall,
|
||||||
boolean batteryLockscreenUnpluggedPercent,
|
boolean batteryLockscreenUnpluggedPercent,
|
||||||
boolean batteryAodUnpluggedPercent,
|
boolean batteryAodUnpluggedPercent,
|
||||||
@@ -374,6 +451,7 @@ public final class SbtSettings {
|
|||||||
String layoutChipMiddleSide,
|
String layoutChipMiddleSide,
|
||||||
boolean layoutChipMiddleAutoNearestSide,
|
boolean layoutChipMiddleAutoNearestSide,
|
||||||
int layoutChipVerticalOffsetPx,
|
int layoutChipVerticalOffsetPx,
|
||||||
|
int layoutChipHeightSteps,
|
||||||
String layoutNotifPosition,
|
String layoutNotifPosition,
|
||||||
String layoutNotifSortOrder,
|
String layoutNotifSortOrder,
|
||||||
boolean layoutNotifShowDotIfTruncated,
|
boolean layoutNotifShowDotIfTruncated,
|
||||||
@@ -383,6 +461,9 @@ public final class SbtSettings {
|
|||||||
String layoutNotifMiddleSide,
|
String layoutNotifMiddleSide,
|
||||||
boolean layoutNotifMiddleAutoNearestSide,
|
boolean layoutNotifMiddleAutoNearestSide,
|
||||||
int layoutNotifVerticalOffsetPx,
|
int layoutNotifVerticalOffsetPx,
|
||||||
|
int layoutNotifIconHeightSteps,
|
||||||
|
int layoutNotifLockIconHeightSteps,
|
||||||
|
int layoutNotifAodIconHeightSteps,
|
||||||
int layoutNotifUnlockedCount,
|
int layoutNotifUnlockedCount,
|
||||||
String[] layoutNotifPositions,
|
String[] layoutNotifPositions,
|
||||||
String[] layoutNotifMiddleSides,
|
String[] layoutNotifMiddleSides,
|
||||||
@@ -393,6 +474,11 @@ public final class SbtSettings {
|
|||||||
String[] layoutNotifLockMiddleSides,
|
String[] layoutNotifLockMiddleSides,
|
||||||
boolean[] layoutNotifLockMiddleAutoNearestSides,
|
boolean[] layoutNotifLockMiddleAutoNearestSides,
|
||||||
int[] layoutNotifLockVerticalOffsetsPx,
|
int[] layoutNotifLockVerticalOffsetsPx,
|
||||||
|
int layoutNotifAodCount,
|
||||||
|
String[] layoutNotifAodPositions,
|
||||||
|
String[] layoutNotifAodMiddleSides,
|
||||||
|
boolean[] layoutNotifAodMiddleAutoNearestSides,
|
||||||
|
int[] layoutNotifAodVerticalOffsetsPx,
|
||||||
String layoutStatusPosition,
|
String layoutStatusPosition,
|
||||||
boolean layoutStatusEnabledAod,
|
boolean layoutStatusEnabledAod,
|
||||||
boolean layoutStatusEnabledLockscreen,
|
boolean layoutStatusEnabledLockscreen,
|
||||||
@@ -401,6 +487,9 @@ public final class SbtSettings {
|
|||||||
String layoutStatusMiddleSide,
|
String layoutStatusMiddleSide,
|
||||||
boolean layoutStatusMiddleAutoNearestSide,
|
boolean layoutStatusMiddleAutoNearestSide,
|
||||||
int layoutStatusVerticalOffsetPx,
|
int layoutStatusVerticalOffsetPx,
|
||||||
|
int layoutStatusIconHeightSteps,
|
||||||
|
int layoutStatusLockIconHeightSteps,
|
||||||
|
int layoutStatusAodIconHeightSteps,
|
||||||
int layoutStatusUnlockedCount,
|
int layoutStatusUnlockedCount,
|
||||||
String[] layoutStatusPositions,
|
String[] layoutStatusPositions,
|
||||||
String[] layoutStatusMiddleSides,
|
String[] layoutStatusMiddleSides,
|
||||||
@@ -411,6 +500,11 @@ public final class SbtSettings {
|
|||||||
String[] layoutStatusLockMiddleSides,
|
String[] layoutStatusLockMiddleSides,
|
||||||
boolean[] layoutStatusLockMiddleAutoNearestSides,
|
boolean[] layoutStatusLockMiddleAutoNearestSides,
|
||||||
int[] layoutStatusLockVerticalOffsetsPx,
|
int[] layoutStatusLockVerticalOffsetsPx,
|
||||||
|
int layoutStatusAodCount,
|
||||||
|
String[] layoutStatusAodPositions,
|
||||||
|
String[] layoutStatusAodMiddleSides,
|
||||||
|
boolean[] layoutStatusAodMiddleAutoNearestSides,
|
||||||
|
int[] layoutStatusAodVerticalOffsetsPx,
|
||||||
Map<String, String> clockCameraTypeOverrides,
|
Map<String, String> clockCameraTypeOverrides,
|
||||||
Map<String, Integer> systemIconBlockedModes,
|
Map<String, Integer> systemIconBlockedModes,
|
||||||
boolean statusChipsHideAll,
|
boolean statusChipsHideAll,
|
||||||
@@ -424,7 +518,8 @@ public final class SbtSettings {
|
|||||||
boolean debugVisualizeStatusContainer,
|
boolean debugVisualizeStatusContainer,
|
||||||
boolean debugVisualizeClockContainer,
|
boolean debugVisualizeClockContainer,
|
||||||
boolean debugVisualizeChipContainer,
|
boolean debugVisualizeChipContainer,
|
||||||
boolean debugVisualizeCameraCutout) {
|
boolean debugVisualizeCameraCutout,
|
||||||
|
boolean debugVisualizeAodStockContainers) {
|
||||||
this.enableAodCutoutLimit = enableAodCutoutLimit;
|
this.enableAodCutoutLimit = enableAodCutoutLimit;
|
||||||
this.enableLockCutoutLimit = enableLockCutoutLimit;
|
this.enableLockCutoutLimit = enableLockCutoutLimit;
|
||||||
this.unlockedMaxIconsPerRow = unlockedMaxIconsPerRow;
|
this.unlockedMaxIconsPerRow = unlockedMaxIconsPerRow;
|
||||||
@@ -438,10 +533,12 @@ public final class SbtSettings {
|
|||||||
this.cardsAodMaxRows = cardsAodMaxRows;
|
this.cardsAodMaxRows = cardsAodMaxRows;
|
||||||
this.cardsAodEvenDistribution = cardsAodEvenDistribution;
|
this.cardsAodEvenDistribution = cardsAodEvenDistribution;
|
||||||
this.cardsAodLimitToWidth = cardsAodLimitToWidth;
|
this.cardsAodLimitToWidth = cardsAodLimitToWidth;
|
||||||
|
this.cardsAodIconHeightSteps = clampIconHeightSteps(cardsAodIconHeightSteps);
|
||||||
this.cardsLockMaxIconsPerRow = cardsLockMaxIconsPerRow;
|
this.cardsLockMaxIconsPerRow = cardsLockMaxIconsPerRow;
|
||||||
this.cardsLockMaxRows = cardsLockMaxRows;
|
this.cardsLockMaxRows = cardsLockMaxRows;
|
||||||
this.cardsLockEvenDistribution = cardsLockEvenDistribution;
|
this.cardsLockEvenDistribution = cardsLockEvenDistribution;
|
||||||
this.cardsLockLimitToWidth = cardsLockLimitToWidth;
|
this.cardsLockLimitToWidth = cardsLockLimitToWidth;
|
||||||
|
this.cardsLockIconHeightSteps = clampIconHeightSteps(cardsLockIconHeightSteps);
|
||||||
this.keepAodVisibleDuringCall = keepAodVisibleDuringCall;
|
this.keepAodVisibleDuringCall = keepAodVisibleDuringCall;
|
||||||
this.batteryLockscreenUnpluggedPercent = batteryLockscreenUnpluggedPercent;
|
this.batteryLockscreenUnpluggedPercent = batteryLockscreenUnpluggedPercent;
|
||||||
this.batteryAodUnpluggedPercent = batteryAodUnpluggedPercent;
|
this.batteryAodUnpluggedPercent = batteryAodUnpluggedPercent;
|
||||||
@@ -550,6 +647,7 @@ public final class SbtSettings {
|
|||||||
layoutChipVerticalOffsetPx,
|
layoutChipVerticalOffsetPx,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
|
this.layoutChipHeightSteps = clampIconHeightSteps(layoutChipHeightSteps);
|
||||||
this.layoutNotifPosition = layoutNotifPosition != null
|
this.layoutNotifPosition = layoutNotifPosition != null
|
||||||
? layoutNotifPosition
|
? layoutNotifPosition
|
||||||
: SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT;
|
: SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT;
|
||||||
@@ -568,6 +666,9 @@ public final class SbtSettings {
|
|||||||
layoutNotifVerticalOffsetPx,
|
layoutNotifVerticalOffsetPx,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
|
this.layoutNotifIconHeightSteps = clampIconHeightSteps(layoutNotifIconHeightSteps);
|
||||||
|
this.layoutNotifLockIconHeightSteps = clampIconHeightSteps(layoutNotifLockIconHeightSteps);
|
||||||
|
this.layoutNotifAodIconHeightSteps = clampIconHeightSteps(layoutNotifAodIconHeightSteps);
|
||||||
this.layoutNotifUnlockedCount = Math.max(
|
this.layoutNotifUnlockedCount = Math.max(
|
||||||
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MIN,
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MIN,
|
||||||
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, layoutNotifUnlockedCount));
|
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, layoutNotifUnlockedCount));
|
||||||
@@ -608,6 +709,25 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
|
this.layoutNotifAodCount = clampIconContainerCount(layoutNotifAodCount);
|
||||||
|
this.layoutNotifAodPositions = sanitizeStringArray(
|
||||||
|
layoutNotifAodPositions,
|
||||||
|
this.layoutNotifPosition,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutNotifAodMiddleSides = sanitizeStringArray(
|
||||||
|
layoutNotifAodMiddleSides,
|
||||||
|
this.layoutNotifMiddleSide,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutNotifAodMiddleAutoNearestSides = sanitizeBooleanArray(
|
||||||
|
layoutNotifAodMiddleAutoNearestSides,
|
||||||
|
this.layoutNotifMiddleAutoNearestSide,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutNotifAodVerticalOffsetsPx = sanitizeIntArray(
|
||||||
|
layoutNotifAodVerticalOffsetsPx,
|
||||||
|
this.layoutNotifVerticalOffsetPx,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
||||||
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
this.layoutStatusPosition = layoutStatusPosition != null
|
this.layoutStatusPosition = layoutStatusPosition != null
|
||||||
? layoutStatusPosition
|
? layoutStatusPosition
|
||||||
: SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT;
|
: SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT;
|
||||||
@@ -623,6 +743,9 @@ public final class SbtSettings {
|
|||||||
layoutStatusVerticalOffsetPx,
|
layoutStatusVerticalOffsetPx,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
|
this.layoutStatusIconHeightSteps = clampIconHeightSteps(layoutStatusIconHeightSteps);
|
||||||
|
this.layoutStatusLockIconHeightSteps = clampIconHeightSteps(layoutStatusLockIconHeightSteps);
|
||||||
|
this.layoutStatusAodIconHeightSteps = clampIconHeightSteps(layoutStatusAodIconHeightSteps);
|
||||||
this.layoutStatusUnlockedCount = Math.max(
|
this.layoutStatusUnlockedCount = Math.max(
|
||||||
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MIN,
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MIN,
|
||||||
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, layoutStatusUnlockedCount));
|
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, layoutStatusUnlockedCount));
|
||||||
@@ -663,6 +786,25 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
|
this.layoutStatusAodCount = clampIconContainerCount(layoutStatusAodCount);
|
||||||
|
this.layoutStatusAodPositions = sanitizeStringArray(
|
||||||
|
layoutStatusAodPositions,
|
||||||
|
this.layoutStatusPosition,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutStatusAodMiddleSides = sanitizeStringArray(
|
||||||
|
layoutStatusAodMiddleSides,
|
||||||
|
this.layoutStatusMiddleSide,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutStatusAodMiddleAutoNearestSides = sanitizeBooleanArray(
|
||||||
|
layoutStatusAodMiddleAutoNearestSides,
|
||||||
|
this.layoutStatusMiddleAutoNearestSide,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX);
|
||||||
|
this.layoutStatusAodVerticalOffsetsPx = sanitizeIntArray(
|
||||||
|
layoutStatusAodVerticalOffsetsPx,
|
||||||
|
this.layoutStatusVerticalOffsetPx,
|
||||||
|
SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX,
|
||||||
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MIN,
|
||||||
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX);
|
||||||
this.clockCameraTypeOverrides = clockCameraTypeOverrides != null
|
this.clockCameraTypeOverrides = clockCameraTypeOverrides != null
|
||||||
? Collections.unmodifiableMap(new HashMap<>(clockCameraTypeOverrides))
|
? Collections.unmodifiableMap(new HashMap<>(clockCameraTypeOverrides))
|
||||||
: Collections.emptyMap();
|
: Collections.emptyMap();
|
||||||
@@ -694,6 +836,7 @@ public final class SbtSettings {
|
|||||||
this.debugVisualizeClockContainer = debugVisualizeClockContainer;
|
this.debugVisualizeClockContainer = debugVisualizeClockContainer;
|
||||||
this.debugVisualizeChipContainer = debugVisualizeChipContainer;
|
this.debugVisualizeChipContainer = debugVisualizeChipContainer;
|
||||||
this.debugVisualizeCameraCutout = debugVisualizeCameraCutout;
|
this.debugVisualizeCameraCutout = debugVisualizeCameraCutout;
|
||||||
|
this.debugVisualizeAodStockContainers = debugVisualizeAodStockContainers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SbtSettings defaults() {
|
public static SbtSettings defaults() {
|
||||||
@@ -711,10 +854,12 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.CARDS_AOD_MAX_ROWS_DEFAULT,
|
SbtDefaults.CARDS_AOD_MAX_ROWS_DEFAULT,
|
||||||
SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT,
|
SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT,
|
||||||
SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT,
|
SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT,
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ROWS_DEFAULT,
|
SbtDefaults.CARDS_LOCK_MAX_ROWS_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT,
|
SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT,
|
SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT,
|
SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT,
|
||||||
SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT,
|
SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT,
|
||||||
SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT,
|
SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT,
|
||||||
@@ -761,6 +906,7 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT,
|
SbtDefaults.LAYOUT_CHIP_MIDDLE_SIDE_DEFAULT,
|
||||||
SbtDefaults.LAYOUT_CHIP_MIDDLE_AUTO_NEAREST_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_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_SHOW_DOT_IF_TRUNCATED_DEFAULT,
|
||||||
@@ -770,6 +916,14 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
|
||||||
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_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_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
|
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -788,6 +942,14 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
|
||||||
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_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_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
|
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
@@ -811,7 +973,8 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.DEBUG_VISUALIZE_STATUS_CONTAINER_DEFAULT,
|
SbtDefaults.DEBUG_VISUALIZE_STATUS_CONTAINER_DEFAULT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CLOCK_CONTAINER_DEFAULT,
|
SbtDefaults.DEBUG_VISUALIZE_CLOCK_CONTAINER_DEFAULT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT,
|
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT
|
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT,
|
||||||
|
SbtDefaults.DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -872,20 +1035,25 @@ public final class SbtSettings {
|
|||||||
if (context == null || !AppIconRules.isValidPackageName(packageName)) {
|
if (context == null || !AppIconRules.isValidPackageName(packageName)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
long seenMs = firstSeenMs > 0L ? firstSeenMs : System.currentTimeMillis();
|
||||||
|
int offsetMinutes = AppIconRules.currentTimezoneOffsetMinutes();
|
||||||
try {
|
try {
|
||||||
if (!MODULE_PACKAGE.equals(context.getPackageName()) && hasSettingsProvider(context)) {
|
if (!MODULE_PACKAGE.equals(context.getPackageName()) && hasSettingsProvider(context)) {
|
||||||
Uri uri = Uri.parse("content://" + SbtSettingsProvider.AUTHORITY);
|
Uri uri = Uri.parse("content://" + SbtSettingsProvider.AUTHORITY);
|
||||||
Bundle extras = new Bundle();
|
Bundle extras = new Bundle();
|
||||||
extras.putString(AppIconRules.EXTRA_PACKAGE, packageName);
|
extras.putString(AppIconRules.EXTRA_PACKAGE, packageName);
|
||||||
extras.putLong(AppIconRules.EXTRA_FIRST_SEEN_MS, firstSeenMs);
|
extras.putLong(AppIconRules.EXTRA_FIRST_SEEN_MS, seenMs);
|
||||||
|
extras.putLong(AppIconRules.EXTRA_LAST_SEEN_MS, seenMs);
|
||||||
|
extras.putInt(AppIconRules.EXTRA_LAST_SEEN_TIMEZONE_OFFSET_MINUTES, offsetMinutes);
|
||||||
context.getContentResolver()
|
context.getContentResolver()
|
||||||
.call(uri, SbtSettingsProvider.METHOD_NOTE_SEEN_ICON_APP, null, extras);
|
.call(uri, SbtSettingsProvider.METHOD_NOTE_SEEN_ICON_APP, null, extras);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||||
Map<String, Long> seen = AppIconRules.loadSeenSession(prefs);
|
Map<String, AppIconRules.SeenApp> seen = AppIconRules.loadSeenSession(prefs);
|
||||||
AppIconRules.noteSeen(seen, packageName, firstSeenMs);
|
if (AppIconRules.noteSeen(seen, packageName, seenMs, offsetMinutes)) {
|
||||||
AppIconRules.saveSeenSession(prefs, seen);
|
AppIconRules.saveSeenSession(prefs, seen);
|
||||||
|
}
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
// This list is advisory UI state; rendering should never fail because it cannot be updated.
|
// This list is advisory UI state; rendering should never fail because it cannot be updated.
|
||||||
}
|
}
|
||||||
@@ -932,6 +1100,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.CARDS_AOD_MAX_ROWS_MAX),
|
SbtDefaults.CARDS_AOD_MAX_ROWS_MAX),
|
||||||
prefs.getBoolean(KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT),
|
prefs.getBoolean(KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT),
|
||||||
prefs.getBoolean(KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT),
|
prefs.getBoolean(KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT),
|
||||||
|
clampInt(prefs.getInt(KEY_CARDS_AOD_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
clampInt(prefs.getInt(KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT),
|
clampInt(prefs.getInt(KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT),
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MIN,
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MIN,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MAX),
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MAX),
|
||||||
@@ -940,6 +1112,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.CARDS_LOCK_MAX_ROWS_MAX),
|
SbtDefaults.CARDS_LOCK_MAX_ROWS_MAX),
|
||||||
prefs.getBoolean(KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT),
|
prefs.getBoolean(KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT),
|
||||||
prefs.getBoolean(KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT),
|
prefs.getBoolean(KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT),
|
||||||
|
clampInt(prefs.getInt(KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
prefs.getBoolean(KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT),
|
prefs.getBoolean(KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT),
|
||||||
prefs.getBoolean(KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT),
|
prefs.getBoolean(KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT),
|
||||||
prefs.getBoolean(KEY_BATTERY_AOD_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT),
|
prefs.getBoolean(KEY_BATTERY_AOD_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT),
|
||||||
@@ -1007,6 +1183,8 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampIconHeightSteps(prefs.getInt(KEY_LAYOUT_CHIP_HEIGHT_STEPS,
|
||||||
|
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_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT),
|
||||||
@@ -1019,6 +1197,18 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampInt(prefs.getInt(KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(prefs.getInt(layoutLockNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(prefs.getInt(layoutAodNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
readIconContainerCount(
|
readIconContainerCount(
|
||||||
prefs,
|
prefs,
|
||||||
KEY_LAYOUT_NOTIF_UNLOCKED_COUNT,
|
KEY_LAYOUT_NOTIF_UNLOCKED_COUNT,
|
||||||
@@ -1063,6 +1253,28 @@ public final class SbtSettings {
|
|||||||
prefs,
|
prefs,
|
||||||
SbtSettings::layoutLockNotifVerticalOffsetKey,
|
SbtSettings::layoutLockNotifVerticalOffsetKey,
|
||||||
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
|
readIconContainerCount(
|
||||||
|
prefs,
|
||||||
|
"layout_aod_notifications_count",
|
||||||
|
KEY_LAYOUT_NOTIF_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT),
|
||||||
|
readStringArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodNotifPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT),
|
||||||
|
readStringArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodNotifMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
|
||||||
|
readBooleanArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
|
||||||
|
readIntArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodNotifVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
prefs.getString(KEY_LAYOUT_STATUS_POSITION, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
prefs.getString(KEY_LAYOUT_STATUS_POSITION, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
||||||
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),
|
||||||
@@ -1074,6 +1286,18 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampInt(prefs.getInt(KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(prefs.getInt(layoutLockStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(prefs.getInt(layoutAodStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
readIconContainerCount(
|
readIconContainerCount(
|
||||||
prefs,
|
prefs,
|
||||||
KEY_LAYOUT_STATUS_UNLOCKED_COUNT,
|
KEY_LAYOUT_STATUS_UNLOCKED_COUNT,
|
||||||
@@ -1118,6 +1342,28 @@ public final class SbtSettings {
|
|||||||
prefs,
|
prefs,
|
||||||
SbtSettings::layoutLockStatusVerticalOffsetKey,
|
SbtSettings::layoutLockStatusVerticalOffsetKey,
|
||||||
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
|
readIconContainerCount(
|
||||||
|
prefs,
|
||||||
|
"layout_aod_status_count",
|
||||||
|
KEY_LAYOUT_STATUS_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT),
|
||||||
|
readStringArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodStatusPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
||||||
|
readStringArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodStatusMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
|
||||||
|
readBooleanArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
|
||||||
|
readIntArrayFromPrefs(
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodStatusVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
ClockCameraTypeSupport.parseOverrides(copyStringSet(
|
ClockCameraTypeSupport.parseOverrides(copyStringSet(
|
||||||
prefs.getStringSet(KEY_CLOCK_CAMERA_TYPE_OVERRIDES, Collections.emptySet()))),
|
prefs.getStringSet(KEY_CLOCK_CAMERA_TYPE_OVERRIDES, Collections.emptySet()))),
|
||||||
systemIconBlockedModes,
|
systemIconBlockedModes,
|
||||||
@@ -1144,7 +1390,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT),
|
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT),
|
||||||
prefs.getBoolean(
|
prefs.getBoolean(
|
||||||
KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT)
|
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT),
|
||||||
|
prefs.getBoolean(
|
||||||
|
KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS,
|
||||||
|
SbtDefaults.DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1181,6 +1430,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.CARDS_AOD_MAX_ROWS_MAX),
|
SbtDefaults.CARDS_AOD_MAX_ROWS_MAX),
|
||||||
bundle.getBoolean(KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT),
|
bundle.getBoolean(KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT),
|
||||||
bundle.getBoolean(KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT),
|
bundle.getBoolean(KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT),
|
||||||
|
clampInt(bundle.getInt(KEY_CARDS_AOD_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
clampInt(bundle.getInt(KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT),
|
clampInt(bundle.getInt(KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT),
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MIN,
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MIN,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MAX),
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_MAX),
|
||||||
@@ -1189,6 +1442,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.CARDS_LOCK_MAX_ROWS_MAX),
|
SbtDefaults.CARDS_LOCK_MAX_ROWS_MAX),
|
||||||
bundle.getBoolean(KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT),
|
bundle.getBoolean(KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT),
|
||||||
bundle.getBoolean(KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT),
|
bundle.getBoolean(KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT),
|
||||||
|
clampInt(bundle.getInt(KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
bundle.getBoolean(KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT),
|
bundle.getBoolean(KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT),
|
||||||
bundle.getBoolean(KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT),
|
bundle.getBoolean(KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT_DEFAULT),
|
||||||
bundle.getBoolean(KEY_BATTERY_AOD_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT),
|
bundle.getBoolean(KEY_BATTERY_AOD_UNPLUGGED_PERCENT, SbtDefaults.BATTERY_AOD_UNPLUGGED_PERCENT_DEFAULT),
|
||||||
@@ -1254,6 +1511,8 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampIconHeightSteps(bundle.getInt(KEY_LAYOUT_CHIP_HEIGHT_STEPS,
|
||||||
|
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_SHOW_DOT_IF_TRUNCATED, SbtDefaults.LAYOUT_NOTIF_SHOW_DOT_IF_TRUNCATED_DEFAULT),
|
||||||
@@ -1266,6 +1525,18 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampInt(bundle.getInt(KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(bundle.getInt(layoutLockNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(bundle.getInt(layoutAodNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
readIconContainerCount(
|
readIconContainerCount(
|
||||||
bundle,
|
bundle,
|
||||||
KEY_LAYOUT_NOTIF_UNLOCKED_COUNT,
|
KEY_LAYOUT_NOTIF_UNLOCKED_COUNT,
|
||||||
@@ -1310,6 +1581,28 @@ public final class SbtSettings {
|
|||||||
bundle,
|
bundle,
|
||||||
SbtSettings::layoutLockNotifVerticalOffsetKey,
|
SbtSettings::layoutLockNotifVerticalOffsetKey,
|
||||||
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
|
readIconContainerCount(
|
||||||
|
bundle,
|
||||||
|
"layout_aod_notifications_count",
|
||||||
|
KEY_LAYOUT_NOTIF_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT),
|
||||||
|
readStringArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodNotifPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT),
|
||||||
|
readStringArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodNotifMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT),
|
||||||
|
readBooleanArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
|
||||||
|
readIntArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodNotifVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
bundle.getString(KEY_LAYOUT_STATUS_POSITION, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
bundle.getString(KEY_LAYOUT_STATUS_POSITION, SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
||||||
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),
|
||||||
@@ -1321,6 +1614,18 @@ public final class SbtSettings {
|
|||||||
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,
|
||||||
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
SbtDefaults.CLOCK_VERTICAL_OFFSET_PX_MAX),
|
||||||
|
clampInt(bundle.getInt(KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(bundle.getInt(layoutLockStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
clampInt(bundle.getInt(layoutAodStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
readIconContainerCount(
|
readIconContainerCount(
|
||||||
bundle,
|
bundle,
|
||||||
KEY_LAYOUT_STATUS_UNLOCKED_COUNT,
|
KEY_LAYOUT_STATUS_UNLOCKED_COUNT,
|
||||||
@@ -1365,6 +1670,28 @@ public final class SbtSettings {
|
|||||||
bundle,
|
bundle,
|
||||||
SbtSettings::layoutLockStatusVerticalOffsetKey,
|
SbtSettings::layoutLockStatusVerticalOffsetKey,
|
||||||
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
|
readIconContainerCount(
|
||||||
|
bundle,
|
||||||
|
"layout_aod_status_count",
|
||||||
|
KEY_LAYOUT_STATUS_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT),
|
||||||
|
readStringArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodStatusPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT),
|
||||||
|
readStringArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodStatusMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT),
|
||||||
|
readBooleanArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT),
|
||||||
|
readIntArrayFromBundle(
|
||||||
|
bundle,
|
||||||
|
SbtSettings::layoutAodStatusVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT),
|
||||||
ClockCameraTypeSupport.parseOverrides(readStringSetFromBundle(bundle, KEY_CLOCK_CAMERA_TYPE_OVERRIDES)),
|
ClockCameraTypeSupport.parseOverrides(readStringSetFromBundle(bundle, KEY_CLOCK_CAMERA_TYPE_OVERRIDES)),
|
||||||
systemIconBlockedModes,
|
systemIconBlockedModes,
|
||||||
bundle.getBoolean(KEY_STATUS_CHIPS_HIDE_ALL, false),
|
bundle.getBoolean(KEY_STATUS_CHIPS_HIDE_ALL, false),
|
||||||
@@ -1388,7 +1715,10 @@ public final class SbtSettings {
|
|||||||
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT),
|
SbtDefaults.DEBUG_VISUALIZE_CHIP_CONTAINER_DEFAULT),
|
||||||
bundle.getBoolean(
|
bundle.getBoolean(
|
||||||
KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT)
|
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT),
|
||||||
|
bundle.getBoolean(
|
||||||
|
KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS,
|
||||||
|
SbtDefaults.DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1406,6 +1736,12 @@ public final class SbtSettings {
|
|||||||
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, value));
|
Math.min(SbtDefaults.LAYOUT_ICON_CONTAINER_COUNT_MAX, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int clampIconHeightSteps(int value) {
|
||||||
|
return Math.max(
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
Math.min(SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX, value));
|
||||||
|
}
|
||||||
|
|
||||||
private static int readIconContainerCount(
|
private static int readIconContainerCount(
|
||||||
SharedPreferences prefs,
|
SharedPreferences prefs,
|
||||||
String countKey,
|
String countKey,
|
||||||
|
|||||||
+78
-3
@@ -71,6 +71,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
prefs.getBoolean(SbtSettings.KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT));
|
prefs.getBoolean(SbtSettings.KEY_CARDS_AOD_EVEN_DISTRIBUTION, SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT));
|
||||||
out.putBoolean(SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH,
|
out.putBoolean(SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH,
|
||||||
prefs.getBoolean(SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT));
|
prefs.getBoolean(SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH, SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT));
|
||||||
|
out.putInt(SbtSettings.KEY_CARDS_AOD_ICON_HEIGHT_STEPS,
|
||||||
|
prefs.getInt(SbtSettings.KEY_CARDS_AOD_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
out.putInt(SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW,
|
out.putInt(SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW,
|
||||||
prefs.getInt(SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT));
|
prefs.getInt(SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW, SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT));
|
||||||
out.putInt(SbtSettings.KEY_CARDS_LOCK_MAX_ROWS,
|
out.putInt(SbtSettings.KEY_CARDS_LOCK_MAX_ROWS,
|
||||||
@@ -79,6 +82,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
prefs.getBoolean(SbtSettings.KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT));
|
prefs.getBoolean(SbtSettings.KEY_CARDS_LOCK_EVEN_DISTRIBUTION, SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT));
|
||||||
out.putBoolean(SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
out.putBoolean(SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
||||||
prefs.getBoolean(SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT));
|
prefs.getBoolean(SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH, SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT));
|
||||||
|
out.putInt(SbtSettings.KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
|
prefs.getInt(SbtSettings.KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
out.putBoolean(SbtSettings.KEY_AOD_KEEP_VISIBLE_DURING_CALL,
|
out.putBoolean(SbtSettings.KEY_AOD_KEEP_VISIBLE_DURING_CALL,
|
||||||
prefs.getBoolean(SbtSettings.KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT));
|
prefs.getBoolean(SbtSettings.KEY_AOD_KEEP_VISIBLE_DURING_CALL, SbtDefaults.AOD_KEEP_VISIBLE_DURING_CALL_DEFAULT));
|
||||||
out.putBoolean(SbtSettings.KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT,
|
out.putBoolean(SbtSettings.KEY_BATTERY_LOCKSCREEN_UNPLUGGED_PERCENT,
|
||||||
@@ -157,6 +163,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
out.putBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
out.putBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
||||||
prefs.getBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
prefs.getBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT));
|
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT));
|
||||||
|
out.putBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS,
|
||||||
|
prefs.getBoolean(SbtSettings.KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS,
|
||||||
|
SbtDefaults.DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT));
|
||||||
out.putInt(SbtSettings.KEY_LAYOUT_PADDING_CUTOUT_PX,
|
out.putInt(SbtSettings.KEY_LAYOUT_PADDING_CUTOUT_PX,
|
||||||
prefs.getInt(SbtSettings.KEY_LAYOUT_PADDING_CUTOUT_PX,
|
prefs.getInt(SbtSettings.KEY_LAYOUT_PADDING_CUTOUT_PX,
|
||||||
SbtDefaults.LAYOUT_PADDING_CUTOUT_PX_DEFAULT));
|
SbtDefaults.LAYOUT_PADDING_CUTOUT_PX_DEFAULT));
|
||||||
@@ -216,6 +225,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
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));
|
||||||
|
out.putInt(SbtSettings.KEY_LAYOUT_CHIP_HEIGHT_STEPS,
|
||||||
|
prefs.getInt(SbtSettings.KEY_LAYOUT_CHIP_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT));
|
||||||
out.putString(SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
|
out.putString(SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
|
||||||
prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
|
prefs.getString(SbtSettings.KEY_LAYOUT_NOTIF_POSITION,
|
||||||
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT));
|
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT));
|
||||||
@@ -250,6 +262,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
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));
|
||||||
|
out.putInt(SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
|
||||||
|
prefs.getInt(SbtSettings.KEY_LAYOUT_NOTIF_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
putIconCopySettings(
|
putIconCopySettings(
|
||||||
out,
|
out,
|
||||||
prefs,
|
prefs,
|
||||||
@@ -268,6 +283,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT)
|
SbtDefaults.LAYOUT_NOTIF_ENABLED_LOCKSCREEN_DEFAULT)
|
||||||
? SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT
|
? SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT
|
||||||
: 0));
|
: 0));
|
||||||
|
out.putInt(SbtSettings.layoutLockNotifIconHeightKey(),
|
||||||
|
prefs.getInt(SbtSettings.layoutLockNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
putIconCopySettings(
|
putIconCopySettings(
|
||||||
out,
|
out,
|
||||||
prefs,
|
prefs,
|
||||||
@@ -279,6 +297,27 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
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("layout_aod_notifications_count",
|
||||||
|
prefs.getInt("layout_aod_notifications_count",
|
||||||
|
prefs.getBoolean(
|
||||||
|
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_ENABLED_AOD_DEFAULT)
|
||||||
|
? SbtDefaults.LAYOUT_NOTIF_UNLOCKED_COUNT_DEFAULT
|
||||||
|
: 0));
|
||||||
|
out.putInt(SbtSettings.layoutAodNotifIconHeightKey(),
|
||||||
|
prefs.getInt(SbtSettings.layoutAodNotifIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
|
putIconCopySettings(
|
||||||
|
out,
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodNotifPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_POSITION_DEFAULT,
|
||||||
|
SbtSettings::layoutAodNotifMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_SIDE_DEFAULT,
|
||||||
|
SbtSettings::layoutAodNotifMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
||||||
|
SbtSettings::layoutAodNotifVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_NOTIF_VERTICAL_OFFSET_PX_DEFAULT);
|
||||||
out.putString(SbtSettings.KEY_LAYOUT_STATUS_POSITION,
|
out.putString(SbtSettings.KEY_LAYOUT_STATUS_POSITION,
|
||||||
prefs.getString(SbtSettings.KEY_LAYOUT_STATUS_POSITION,
|
prefs.getString(SbtSettings.KEY_LAYOUT_STATUS_POSITION,
|
||||||
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT));
|
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT));
|
||||||
@@ -310,6 +349,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
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));
|
||||||
|
out.putInt(SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
|
||||||
|
prefs.getInt(SbtSettings.KEY_LAYOUT_STATUS_ICON_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
putIconCopySettings(
|
putIconCopySettings(
|
||||||
out,
|
out,
|
||||||
prefs,
|
prefs,
|
||||||
@@ -328,6 +370,9 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT)
|
SbtDefaults.LAYOUT_STATUS_ENABLED_LOCKSCREEN_DEFAULT)
|
||||||
? SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT
|
? SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT
|
||||||
: 0));
|
: 0));
|
||||||
|
out.putInt(SbtSettings.layoutLockStatusIconHeightKey(),
|
||||||
|
prefs.getInt(SbtSettings.layoutLockStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
putIconCopySettings(
|
putIconCopySettings(
|
||||||
out,
|
out,
|
||||||
prefs,
|
prefs,
|
||||||
@@ -339,6 +384,27 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
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("layout_aod_status_count",
|
||||||
|
prefs.getInt("layout_aod_status_count",
|
||||||
|
prefs.getBoolean(
|
||||||
|
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_AOD,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ENABLED_AOD_DEFAULT)
|
||||||
|
? SbtDefaults.LAYOUT_STATUS_UNLOCKED_COUNT_DEFAULT
|
||||||
|
: 0));
|
||||||
|
out.putInt(SbtSettings.layoutAodStatusIconHeightKey(),
|
||||||
|
prefs.getInt(SbtSettings.layoutAodStatusIconHeightKey(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT));
|
||||||
|
putIconCopySettings(
|
||||||
|
out,
|
||||||
|
prefs,
|
||||||
|
SbtSettings::layoutAodStatusPositionKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_POSITION_DEFAULT,
|
||||||
|
SbtSettings::layoutAodStatusMiddleSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_SIDE_DEFAULT,
|
||||||
|
SbtSettings::layoutAodStatusMiddleAutoNearestSideKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_DEFAULT,
|
||||||
|
SbtSettings::layoutAodStatusVerticalOffsetKey,
|
||||||
|
SbtDefaults.LAYOUT_STATUS_VERTICAL_OFFSET_PX_DEFAULT);
|
||||||
out.putStringArrayList(
|
out.putStringArrayList(
|
||||||
SbtSettings.KEY_CLOCK_CAMERA_TYPE_OVERRIDES,
|
SbtSettings.KEY_CLOCK_CAMERA_TYPE_OVERRIDES,
|
||||||
new ArrayList<>(prefs.getStringSet(
|
new ArrayList<>(prefs.getStringSet(
|
||||||
@@ -372,17 +438,26 @@ public class SbtSettingsProvider extends ContentProvider {
|
|||||||
}
|
}
|
||||||
if (METHOD_NOTE_SEEN_ICON_APP.equals(method)) {
|
if (METHOD_NOTE_SEEN_ICON_APP.equals(method)) {
|
||||||
String pkg = extras != null ? extras.getString(AppIconRules.EXTRA_PACKAGE) : null;
|
String pkg = extras != null ? extras.getString(AppIconRules.EXTRA_PACKAGE) : null;
|
||||||
long firstSeenMs = extras != null
|
long seenMs = extras != null
|
||||||
? extras.getLong(AppIconRules.EXTRA_FIRST_SEEN_MS, System.currentTimeMillis())
|
? extras.getLong(AppIconRules.EXTRA_FIRST_SEEN_MS, System.currentTimeMillis())
|
||||||
: System.currentTimeMillis();
|
: System.currentTimeMillis();
|
||||||
|
if (extras != null && extras.containsKey(AppIconRules.EXTRA_LAST_SEEN_MS)) {
|
||||||
|
seenMs = extras.getLong(AppIconRules.EXTRA_LAST_SEEN_MS, seenMs);
|
||||||
|
}
|
||||||
|
int offsetMinutes = extras != null
|
||||||
|
? extras.getInt(
|
||||||
|
AppIconRules.EXTRA_LAST_SEEN_TIMEZONE_OFFSET_MINUTES,
|
||||||
|
AppIconRules.currentTimezoneOffsetMinutes())
|
||||||
|
: AppIconRules.currentTimezoneOffsetMinutes();
|
||||||
if (!AppIconRules.isValidPackageName(pkg)) {
|
if (!AppIconRules.isValidPackageName(pkg)) {
|
||||||
return Bundle.EMPTY;
|
return Bundle.EMPTY;
|
||||||
}
|
}
|
||||||
synchronized (LOCK) {
|
synchronized (LOCK) {
|
||||||
Map<String, Long> seen = AppIconRules.loadSeenSession(prefs);
|
Map<String, AppIconRules.SeenApp> seen = AppIconRules.loadSeenSession(prefs);
|
||||||
AppIconRules.noteSeen(seen, pkg, firstSeenMs);
|
if (AppIconRules.noteSeen(seen, pkg, seenMs, offsetMinutes)) {
|
||||||
AppIconRules.saveSeenSession(prefs, seen);
|
AppIconRules.saveSeenSession(prefs, seen);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return Bundle.EMPTY;
|
return Bundle.EMPTY;
|
||||||
}
|
}
|
||||||
if (METHOD_SET_CLOCK_CAMERA_DEBUG_STATE.equals(method)) {
|
if (METHOD_SET_CLOCK_CAMERA_DEBUG_STATE.equals(method)) {
|
||||||
|
|||||||
@@ -32,13 +32,16 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
final class HiddenAppsUiSupport {
|
final class HiddenAppsUiSupport {
|
||||||
interface RowChangedListener {
|
interface RowChangedListener {
|
||||||
@@ -81,7 +84,7 @@ final class HiddenAppsUiSupport {
|
|||||||
Map<String, Integer> blocked = AppIconRules.loadBlockedModes(prefs);
|
Map<String, Integer> blocked = AppIconRules.loadBlockedModes(prefs);
|
||||||
Map<String, ArrayList<AppIconRules.ExceptionRule>> exceptionRules =
|
Map<String, ArrayList<AppIconRules.ExceptionRule>> exceptionRules =
|
||||||
AppIconRules.loadExceptionRules(prefs);
|
AppIconRules.loadExceptionRules(prefs);
|
||||||
Map<String, Long> seen = AppIconRules.loadSeenSession(prefs);
|
Map<String, AppIconRules.SeenApp> seen = AppIconRules.loadSeenSession(prefs);
|
||||||
|
|
||||||
ArrayList<RowItem> blockedItems = new ArrayList<>();
|
ArrayList<RowItem> blockedItems = new ArrayList<>();
|
||||||
for (Map.Entry<String, Integer> entry : blocked.entrySet()) {
|
for (Map.Entry<String, Integer> entry : blocked.entrySet()) {
|
||||||
@@ -96,6 +99,7 @@ final class HiddenAppsUiSupport {
|
|||||||
item.blockLock = (mask & AppIconRules.MODE_LOCK) != 0;
|
item.blockLock = (mask & AppIconRules.MODE_LOCK) != 0;
|
||||||
item.blockUnlock = (mask & AppIconRules.MODE_UNLOCK) != 0;
|
item.blockUnlock = (mask & AppIconRules.MODE_UNLOCK) != 0;
|
||||||
item.exceptionRules = toEditableExceptionRules(exceptionRules.get(pkg));
|
item.exceptionRules = toEditableExceptionRules(exceptionRules.get(pkg));
|
||||||
|
applySeenInfo(item, seen.get(pkg));
|
||||||
blockedItems.add(item);
|
blockedItems.add(item);
|
||||||
}
|
}
|
||||||
blockedItems.sort((a, b) -> {
|
blockedItems.sort((a, b) -> {
|
||||||
@@ -122,11 +126,20 @@ final class HiddenAppsUiSupport {
|
|||||||
}
|
}
|
||||||
RowItem item = buildRowItem(context, packageManager, fallbackIcon, seenApp.packageName);
|
RowItem item = buildRowItem(context, packageManager, fallbackIcon, seenApp.packageName);
|
||||||
item.exceptionRules = toEditableExceptionRules(exceptionRules.get(seenApp.packageName));
|
item.exceptionRules = toEditableExceptionRules(exceptionRules.get(seenApp.packageName));
|
||||||
|
applySeenInfo(item, seenApp);
|
||||||
rows.add(item);
|
rows.add(item);
|
||||||
alreadyAdded.add(seenApp.packageName);
|
alreadyAdded.add(seenApp.packageName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void applySeenInfo(RowItem item, AppIconRules.SeenApp seenApp) {
|
||||||
|
if (item == null || seenApp == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
item.lastSeenMs = seenApp.lastSeenMs;
|
||||||
|
item.lastSeenTimezoneOffsetMinutes = seenApp.lastSeenTimezoneOffsetMinutes;
|
||||||
|
}
|
||||||
|
|
||||||
private static RowItem buildRowItem(Context context,
|
private static RowItem buildRowItem(Context context,
|
||||||
PackageManager packageManager,
|
PackageManager packageManager,
|
||||||
Drawable fallbackIcon,
|
Drawable fallbackIcon,
|
||||||
@@ -466,6 +479,41 @@ final class HiddenAppsUiSupport {
|
|||||||
return normalized.isEmpty() ? null : normalized;
|
return normalized.isEmpty() ? null : normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String formatLastSeen(Context context, RowItem row) {
|
||||||
|
if (context == null || row == null || row.lastSeenMs <= 0L) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int offsetMinutes = row.lastSeenTimezoneOffsetMinutes;
|
||||||
|
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
|
||||||
|
format.setTimeZone(timeZoneForOffset(offsetMinutes));
|
||||||
|
String timestamp = format.format(new Date(row.lastSeenMs));
|
||||||
|
int currentOffsetMinutes = AppIconRules.currentTimezoneOffsetMinutes();
|
||||||
|
if (offsetMinutes != currentOffsetMinutes) {
|
||||||
|
timestamp += formatOffsetSuffix(offsetMinutes);
|
||||||
|
}
|
||||||
|
return context.getString(R.string.hidden_apps_last_seen, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TimeZone timeZoneForOffset(int offsetMinutes) {
|
||||||
|
int absMinutes = Math.abs(offsetMinutes);
|
||||||
|
int hours = absMinutes / 60;
|
||||||
|
int minutes = absMinutes % 60;
|
||||||
|
String id = String.format(Locale.ROOT, "GMT%s%02d:%02d",
|
||||||
|
offsetMinutes < 0 ? "-" : "+", hours, minutes);
|
||||||
|
return TimeZone.getTimeZone(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatOffsetSuffix(int offsetMinutes) {
|
||||||
|
int absMinutes = Math.abs(offsetMinutes);
|
||||||
|
int hours = absMinutes / 60;
|
||||||
|
int minutes = absMinutes % 60;
|
||||||
|
if (minutes == 0) {
|
||||||
|
return String.format(Locale.ROOT, "%s%02d", offsetMinutes < 0 ? "-" : "+", hours);
|
||||||
|
}
|
||||||
|
return String.format(Locale.ROOT, "%s%02d:%02d",
|
||||||
|
offsetMinutes < 0 ? "-" : "+", hours, minutes);
|
||||||
|
}
|
||||||
|
|
||||||
static final class RowItem {
|
static final class RowItem {
|
||||||
final String packageName;
|
final String packageName;
|
||||||
final String label;
|
final String label;
|
||||||
@@ -473,6 +521,8 @@ final class HiddenAppsUiSupport {
|
|||||||
boolean blockAod;
|
boolean blockAod;
|
||||||
boolean blockLock;
|
boolean blockLock;
|
||||||
boolean blockUnlock;
|
boolean blockUnlock;
|
||||||
|
long lastSeenMs;
|
||||||
|
int lastSeenTimezoneOffsetMinutes;
|
||||||
ArrayList<EditableExceptionRule> exceptionRules = new ArrayList<>();
|
ArrayList<EditableExceptionRule> exceptionRules = new ArrayList<>();
|
||||||
|
|
||||||
RowItem(String packageName, String label, Drawable icon) {
|
RowItem(String packageName, String label, Drawable icon) {
|
||||||
@@ -520,6 +570,7 @@ final class HiddenAppsUiSupport {
|
|||||||
TextView crossUnlock;
|
TextView crossUnlock;
|
||||||
TextView label;
|
TextView label;
|
||||||
TextView pkg;
|
TextView pkg;
|
||||||
|
TextView lastSeen;
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class HiddenAppsAdapter extends BaseAdapter {
|
static final class HiddenAppsAdapter extends BaseAdapter {
|
||||||
@@ -571,6 +622,7 @@ final class HiddenAppsUiSupport {
|
|||||||
holder.crossUnlock = convertView.findViewById(R.id.icon_mode_unlock_cross);
|
holder.crossUnlock = convertView.findViewById(R.id.icon_mode_unlock_cross);
|
||||||
holder.label = convertView.findViewById(R.id.hidden_item_label);
|
holder.label = convertView.findViewById(R.id.hidden_item_label);
|
||||||
holder.pkg = convertView.findViewById(R.id.hidden_item_package);
|
holder.pkg = convertView.findViewById(R.id.hidden_item_package);
|
||||||
|
holder.lastSeen = convertView.findViewById(R.id.hidden_item_last_seen);
|
||||||
convertView.setTag(holder);
|
convertView.setTag(holder);
|
||||||
} else {
|
} else {
|
||||||
holder = (RowHolder) convertView.getTag();
|
holder = (RowHolder) convertView.getTag();
|
||||||
@@ -585,6 +637,14 @@ final class HiddenAppsUiSupport {
|
|||||||
} else {
|
} else {
|
||||||
holder.pkg.setText(row.packageName);
|
holder.pkg.setText(row.packageName);
|
||||||
}
|
}
|
||||||
|
String lastSeenText = formatLastSeen(context, row);
|
||||||
|
if (lastSeenText == null) {
|
||||||
|
holder.lastSeen.setVisibility(View.GONE);
|
||||||
|
holder.lastSeen.setText("");
|
||||||
|
} else {
|
||||||
|
holder.lastSeen.setVisibility(View.VISIBLE);
|
||||||
|
holder.lastSeen.setText(lastSeenText);
|
||||||
|
}
|
||||||
bindModeIconTriple(
|
bindModeIconTriple(
|
||||||
holder.iconAod, holder.crossAod,
|
holder.iconAod, holder.crossAod,
|
||||||
holder.iconLock, holder.crossLock,
|
holder.iconLock, holder.crossLock,
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public class IconsDebugFragment extends Fragment {
|
|||||||
root.findViewById(R.id.debug_visualize_chip_container_switch);
|
root.findViewById(R.id.debug_visualize_chip_container_switch);
|
||||||
SwitchMaterial visualizeCameraCutoutSwitch =
|
SwitchMaterial visualizeCameraCutoutSwitch =
|
||||||
root.findViewById(R.id.debug_visualize_camera_cutout_switch);
|
root.findViewById(R.id.debug_visualize_camera_cutout_switch);
|
||||||
|
SwitchMaterial visualizeAodStockContainersSwitch =
|
||||||
|
root.findViewById(R.id.debug_visualize_aod_stock_containers_switch);
|
||||||
MaterialButton restartSystemUiButton = root.findViewById(R.id.debug_restart_systemui_button);
|
MaterialButton restartSystemUiButton = root.findViewById(R.id.debug_restart_systemui_button);
|
||||||
SwitchMaterial cycleIconsSwitch = root.findViewById(R.id.debug_cycle_icons_switch);
|
SwitchMaterial cycleIconsSwitch = root.findViewById(R.id.debug_cycle_icons_switch);
|
||||||
TextView currentCameraIdentified = root.findViewById(R.id.debug_camera_current_identified);
|
TextView currentCameraIdentified = root.findViewById(R.id.debug_camera_current_identified);
|
||||||
@@ -106,13 +108,19 @@ public class IconsDebugFragment extends Fragment {
|
|||||||
visualizeCameraCutoutSwitch,
|
visualizeCameraCutoutSwitch,
|
||||||
SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
SbtSettings.KEY_DEBUG_VISUALIZE_CAMERA_CUTOUT,
|
||||||
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT);
|
SbtDefaults.DEBUG_VISUALIZE_CAMERA_CUTOUT_DEFAULT);
|
||||||
|
bindBooleanSwitch(
|
||||||
|
prefs,
|
||||||
|
visualizeAodStockContainersSwitch,
|
||||||
|
SbtSettings.KEY_DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS,
|
||||||
|
SbtDefaults.DEBUG_VISUALIZE_AOD_STOCK_CONTAINERS_DEFAULT);
|
||||||
bindRestartSystemUiButton(restartSystemUiButton);
|
bindRestartSystemUiButton(restartSystemUiButton);
|
||||||
updateVisualizerSwitchAvailability(
|
updateVisualizerSwitchAvailability(
|
||||||
prefs,
|
prefs,
|
||||||
visualizeNotificationContainerSwitch,
|
visualizeNotificationContainerSwitch,
|
||||||
visualizeStatusContainerSwitch,
|
visualizeStatusContainerSwitch,
|
||||||
visualizeClockContainerSwitch,
|
visualizeClockContainerSwitch,
|
||||||
visualizeChipContainerSwitch);
|
visualizeChipContainerSwitch,
|
||||||
|
visualizeAodStockContainersSwitch);
|
||||||
Runnable refreshCameraUi = () -> updateCameraUi(
|
Runnable refreshCameraUi = () -> updateCameraUi(
|
||||||
prefs,
|
prefs,
|
||||||
currentCameraIdentified,
|
currentCameraIdentified,
|
||||||
@@ -134,7 +142,8 @@ public class IconsDebugFragment extends Fragment {
|
|||||||
visualizeNotificationContainerSwitch,
|
visualizeNotificationContainerSwitch,
|
||||||
visualizeStatusContainerSwitch,
|
visualizeStatusContainerSwitch,
|
||||||
visualizeClockContainerSwitch,
|
visualizeClockContainerSwitch,
|
||||||
visualizeChipContainerSwitch);
|
visualizeChipContainerSwitch,
|
||||||
|
visualizeAodStockContainersSwitch);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
prefs.registerOnSharedPreferenceChangeListener(listener);
|
prefs.registerOnSharedPreferenceChangeListener(listener);
|
||||||
@@ -192,7 +201,8 @@ public class IconsDebugFragment extends Fragment {
|
|||||||
SwitchMaterial notificationSwitch,
|
SwitchMaterial notificationSwitch,
|
||||||
SwitchMaterial statusSwitch,
|
SwitchMaterial statusSwitch,
|
||||||
SwitchMaterial clockSwitch,
|
SwitchMaterial clockSwitch,
|
||||||
SwitchMaterial chipSwitch) {
|
SwitchMaterial chipSwitch,
|
||||||
|
SwitchMaterial aodStockSwitch) {
|
||||||
boolean layoutEnabled = prefs != null && prefs.getBoolean(
|
boolean layoutEnabled = prefs != null && prefs.getBoolean(
|
||||||
SbtSettings.KEY_CLOCK_ENABLED,
|
SbtSettings.KEY_CLOCK_ENABLED,
|
||||||
SbtDefaults.CLOCK_ENABLED_DEFAULT);
|
SbtDefaults.CLOCK_ENABLED_DEFAULT);
|
||||||
@@ -208,6 +218,9 @@ public class IconsDebugFragment extends Fragment {
|
|||||||
if (chipSwitch != null) {
|
if (chipSwitch != null) {
|
||||||
chipSwitch.setEnabled(layoutEnabled);
|
chipSwitch.setEnabled(layoutEnabled);
|
||||||
}
|
}
|
||||||
|
if (aodStockSwitch != null) {
|
||||||
|
aodStockSwitch.setEnabled(layoutEnabled);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void restartSystemUi() {
|
private void restartSystemUi() {
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ public final class LayoutFragment extends Fragment {
|
|||||||
root.findViewById(R.id.chip_vertical_offset_plus_fast),
|
root.findViewById(R.id.chip_vertical_offset_plus_fast),
|
||||||
root.findViewById(R.id.chip_vertical_offset_reset),
|
root.findViewById(R.id.chip_vertical_offset_reset),
|
||||||
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT);
|
SbtDefaults.LAYOUT_CHIP_VERTICAL_OFFSET_PX_DEFAULT);
|
||||||
|
addChipHeightControl(root, prefs);
|
||||||
bindStepper(prefs,
|
bindStepper(prefs,
|
||||||
SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
|
SbtSettings.KEY_LAYOUT_STATUS_VERTICAL_OFFSET_PX,
|
||||||
root.findViewById(R.id.status_vertical_offset_input),
|
root.findViewById(R.id.status_vertical_offset_input),
|
||||||
@@ -226,10 +227,12 @@ public final class LayoutFragment extends Fragment {
|
|||||||
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
|
SbtSettings::layoutNotifMiddleAutoNearestSideKey,
|
||||||
SbtSettings::layoutNotifMiddleSideKey,
|
SbtSettings::layoutNotifMiddleSideKey,
|
||||||
SbtSettings::layoutNotifVerticalOffsetKey,
|
SbtSettings::layoutNotifVerticalOffsetKey,
|
||||||
|
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_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,
|
||||||
LayoutSectionCopySupport.Section.NOTIFICATIONS_ICONS);
|
LayoutSectionCopySupport.Section.NOTIFICATIONS_ICONS);
|
||||||
setupUnlockedIconContainerCount(
|
setupUnlockedIconContainerCount(
|
||||||
root,
|
root,
|
||||||
@@ -244,10 +247,12 @@ public final class LayoutFragment extends Fragment {
|
|||||||
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
|
SbtSettings::layoutStatusMiddleAutoNearestSideKey,
|
||||||
SbtSettings::layoutStatusMiddleSideKey,
|
SbtSettings::layoutStatusMiddleSideKey,
|
||||||
SbtSettings::layoutStatusVerticalOffsetKey,
|
SbtSettings::layoutStatusVerticalOffsetKey,
|
||||||
|
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_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,
|
||||||
LayoutSectionCopySupport.Section.STATUS);
|
LayoutSectionCopySupport.Section.STATUS);
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
@@ -269,10 +274,12 @@ public final class LayoutFragment extends Fragment {
|
|||||||
IndexedKey autoNearestKey,
|
IndexedKey autoNearestKey,
|
||||||
IndexedKey middleSideKey,
|
IndexedKey middleSideKey,
|
||||||
IndexedKey verticalOffsetKey,
|
IndexedKey verticalOffsetKey,
|
||||||
|
String iconHeightKey,
|
||||||
String positionDefault,
|
String positionDefault,
|
||||||
boolean autoNearestDefault,
|
boolean autoNearestDefault,
|
||||||
String middleSideDefault,
|
String middleSideDefault,
|
||||||
int verticalOffsetDefault,
|
int verticalOffsetDefault,
|
||||||
|
int iconHeightDefault,
|
||||||
LayoutSectionCopySupport.Section copySection
|
LayoutSectionCopySupport.Section copySection
|
||||||
) {
|
) {
|
||||||
CheckBox checkbox = root.findViewById(checkboxId);
|
CheckBox checkbox = root.findViewById(checkboxId);
|
||||||
@@ -319,6 +326,11 @@ public final class LayoutFragment extends Fragment {
|
|||||||
rebuild[0].run();
|
rebuild[0].run();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
countContainer.addView(iconHeightControl(
|
||||||
|
prefs,
|
||||||
|
iconHeightKey,
|
||||||
|
iconHeightDefault,
|
||||||
|
R.string.layout_icon_height_steps));
|
||||||
int sourceCardIndex = cardsParent != null ? cardsParent.indexOfChild(sourceCard) : -1;
|
int sourceCardIndex = cardsParent != null ? cardsParent.indexOfChild(sourceCard) : -1;
|
||||||
if (cardsParent == null || sourceCardIndex < 0) {
|
if (cardsParent == null || sourceCardIndex < 0) {
|
||||||
return;
|
return;
|
||||||
@@ -407,6 +419,101 @@ public final class LayoutFragment extends Fragment {
|
|||||||
return outer;
|
return outer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View iconHeightControl(
|
||||||
|
SharedPreferences prefs,
|
||||||
|
String key,
|
||||||
|
int defaultValue,
|
||||||
|
int labelRes
|
||||||
|
) {
|
||||||
|
LinearLayout outer = new LinearLayout(requireContext());
|
||||||
|
outer.setOrientation(LinearLayout.VERTICAL);
|
||||||
|
TextView label = new TextView(requireContext());
|
||||||
|
label.setText(labelRes);
|
||||||
|
label.setPadding(0, dp(8), 0, 0);
|
||||||
|
outer.addView(label);
|
||||||
|
|
||||||
|
LinearLayout row = new LinearLayout(requireContext());
|
||||||
|
row.setOrientation(LinearLayout.HORIZONTAL);
|
||||||
|
row.setGravity(android.view.Gravity.CENTER_VERTICAL);
|
||||||
|
MaterialButton minus = smallButton("-");
|
||||||
|
MaterialButton plus = smallButton("+");
|
||||||
|
MaterialButton reset = smallButton("D");
|
||||||
|
EditText input = new EditText(requireContext());
|
||||||
|
input.setGravity(android.view.Gravity.CENTER);
|
||||||
|
input.setSingleLine(true);
|
||||||
|
input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
|
||||||
|
input.setFilters(new InputFilter[]{new InputFilter.LengthFilter(3)});
|
||||||
|
int current = clampValue(
|
||||||
|
prefs.getInt(key, defaultValue),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX);
|
||||||
|
input.setText(String.valueOf(current));
|
||||||
|
row.addView(minus, compactButtonParams());
|
||||||
|
row.addView(input, compactInputParams());
|
||||||
|
row.addView(plus, compactButtonParams());
|
||||||
|
LinearLayout.LayoutParams resetParams = compactButtonParams();
|
||||||
|
resetParams.leftMargin = dp(8);
|
||||||
|
row.addView(reset, resetParams);
|
||||||
|
outer.addView(row);
|
||||||
|
|
||||||
|
View.OnClickListener listener = view -> {
|
||||||
|
int next = clampValue(
|
||||||
|
parseInt(input, current) + (view == minus ? -1 : 1),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX);
|
||||||
|
prefs.edit().putInt(key, next).apply();
|
||||||
|
SbtSettings.ensureReadable(requireContext());
|
||||||
|
input.setText(String.valueOf(next));
|
||||||
|
};
|
||||||
|
minus.setOnClickListener(listener);
|
||||||
|
plus.setOnClickListener(listener);
|
||||||
|
reset.setOnClickListener(v -> {
|
||||||
|
int next = clampValue(
|
||||||
|
defaultValue,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX);
|
||||||
|
prefs.edit().putInt(key, next).apply();
|
||||||
|
SbtSettings.ensureReadable(requireContext());
|
||||||
|
input.setText(String.valueOf(next));
|
||||||
|
});
|
||||||
|
input.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
|
if (!hasFocus) {
|
||||||
|
int next = clampValue(
|
||||||
|
parseInt(input, current),
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX);
|
||||||
|
prefs.edit().putInt(key, next).apply();
|
||||||
|
SbtSettings.ensureReadable(requireContext());
|
||||||
|
input.setText(String.valueOf(next));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return outer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addChipHeightControl(View root, SharedPreferences prefs) {
|
||||||
|
View offsetInput = root.findViewById(R.id.chip_vertical_offset_input);
|
||||||
|
if (offsetInput == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
View row = offsetInput;
|
||||||
|
while (row != null
|
||||||
|
&& !(row instanceof LinearLayout && row.getParent() instanceof LinearLayout)) {
|
||||||
|
if (!(row.getParent() instanceof View)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row = (View) row.getParent();
|
||||||
|
}
|
||||||
|
if (row == null || !(row.getParent() instanceof LinearLayout parent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int index = parent.indexOfChild(row);
|
||||||
|
parent.addView(iconHeightControl(
|
||||||
|
prefs,
|
||||||
|
SbtSettings.KEY_LAYOUT_CHIP_HEIGHT_STEPS,
|
||||||
|
SbtDefaults.LAYOUT_CHIP_HEIGHT_STEPS_DEFAULT,
|
||||||
|
R.string.layout_chip_height_steps), Math.min(parent.getChildCount(), index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
private View iconCopyCardFromLayout(
|
private View iconCopyCardFromLayout(
|
||||||
int sourceCheckboxId,
|
int sourceCheckboxId,
|
||||||
int titleId,
|
int titleId,
|
||||||
|
|||||||
+78
-12
@@ -187,12 +187,14 @@ final class LayoutSectionCopySupport {
|
|||||||
copyInt(editor, prefs, src.maxIcons, dst.maxIcons, src.maxIconsDefault);
|
copyInt(editor, prefs, src.maxIcons, dst.maxIcons, src.maxIconsDefault);
|
||||||
copyBoolean(editor, prefs, src.evenDistribution, dst.evenDistribution, src.evenDistributionDefault);
|
copyBoolean(editor, prefs, src.evenDistribution, dst.evenDistribution, src.evenDistributionDefault);
|
||||||
copyBoolean(editor, prefs, src.limitWidth, dst.limitWidth, src.limitWidthDefault);
|
copyBoolean(editor, prefs, src.limitWidth, dst.limitWidth, src.limitWidthDefault);
|
||||||
|
copyInt(editor, prefs, src.iconHeight, dst.iconHeight, src.iconHeightDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void copyIcons(SharedPreferences.Editor editor, SharedPreferences prefs, KeySet src, KeySet dst) {
|
private static void copyIcons(SharedPreferences.Editor editor, SharedPreferences prefs, KeySet src, KeySet dst) {
|
||||||
copyBoolean(editor, prefs, src.enabled, dst.enabled, src.enabledDefault);
|
copyBoolean(editor, prefs, src.enabled, dst.enabled, src.enabledDefault);
|
||||||
int count = prefs.getInt(src.count, src.countDefault);
|
int count = prefs.getInt(src.count, src.countDefault);
|
||||||
editor.putInt(dst.count, count);
|
editor.putInt(dst.count, count);
|
||||||
|
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);
|
copyBoolean(editor, prefs, src.autoNearestAt(i), dst.autoNearestAt(i), src.autoNearestDefault);
|
||||||
@@ -277,12 +279,14 @@ final class LayoutSectionCopySupport {
|
|||||||
"layout_lock_notifications_middle_auto_nearest_side",
|
"layout_lock_notifications_middle_auto_nearest_side",
|
||||||
"layout_lock_notifications_middle_side",
|
"layout_lock_notifications_middle_side",
|
||||||
"layout_lock_notifications_vertical_offset_px",
|
"layout_lock_notifications_vertical_offset_px",
|
||||||
|
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_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);
|
||||||
}
|
}
|
||||||
if (mode == Mode.AOD) {
|
if (mode == Mode.AOD) {
|
||||||
return iconKeys(
|
return iconKeys(
|
||||||
@@ -292,12 +296,14 @@ final class LayoutSectionCopySupport {
|
|||||||
"layout_aod_notifications_middle_auto_nearest_side",
|
"layout_aod_notifications_middle_auto_nearest_side",
|
||||||
"layout_aod_notifications_middle_side",
|
"layout_aod_notifications_middle_side",
|
||||||
"layout_aod_notifications_vertical_offset_px",
|
"layout_aod_notifications_vertical_offset_px",
|
||||||
|
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_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);
|
||||||
}
|
}
|
||||||
return iconKeys(
|
return iconKeys(
|
||||||
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED,
|
SbtSettings.KEY_LAYOUT_NOTIF_ENABLED_UNLOCKED,
|
||||||
@@ -306,12 +312,14 @@ final class LayoutSectionCopySupport {
|
|||||||
SbtSettings.KEY_LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE,
|
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,
|
||||||
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_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KeySet statusKeys(Mode mode) {
|
private static KeySet statusKeys(Mode mode) {
|
||||||
@@ -323,12 +331,14 @@ final class LayoutSectionCopySupport {
|
|||||||
"layout_lock_status_middle_auto_nearest_side",
|
"layout_lock_status_middle_auto_nearest_side",
|
||||||
"layout_lock_status_middle_side",
|
"layout_lock_status_middle_side",
|
||||||
"layout_lock_status_vertical_offset_px",
|
"layout_lock_status_vertical_offset_px",
|
||||||
|
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_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);
|
||||||
}
|
}
|
||||||
if (mode == Mode.AOD) {
|
if (mode == Mode.AOD) {
|
||||||
return iconKeys(
|
return iconKeys(
|
||||||
@@ -338,12 +348,14 @@ final class LayoutSectionCopySupport {
|
|||||||
"layout_aod_status_middle_auto_nearest_side",
|
"layout_aod_status_middle_auto_nearest_side",
|
||||||
"layout_aod_status_middle_side",
|
"layout_aod_status_middle_side",
|
||||||
"layout_aod_status_vertical_offset_px",
|
"layout_aod_status_vertical_offset_px",
|
||||||
|
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_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);
|
||||||
}
|
}
|
||||||
return iconKeys(
|
return iconKeys(
|
||||||
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED,
|
SbtSettings.KEY_LAYOUT_STATUS_ENABLED_UNLOCKED,
|
||||||
@@ -352,12 +364,14 @@ final class LayoutSectionCopySupport {
|
|||||||
SbtSettings.KEY_LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE,
|
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,
|
||||||
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_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KeySet cardKeys(Mode mode) {
|
private static KeySet cardKeys(Mode mode) {
|
||||||
@@ -367,20 +381,24 @@ final class LayoutSectionCopySupport {
|
|||||||
SbtSettings.KEY_CARDS_AOD_MAX_ICONS_PER_ROW,
|
SbtSettings.KEY_CARDS_AOD_MAX_ICONS_PER_ROW,
|
||||||
SbtSettings.KEY_CARDS_AOD_EVEN_DISTRIBUTION,
|
SbtSettings.KEY_CARDS_AOD_EVEN_DISTRIBUTION,
|
||||||
SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH,
|
SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH,
|
||||||
|
SbtSettings.KEY_CARDS_AOD_ICON_HEIGHT_STEPS,
|
||||||
SbtDefaults.CARDS_AOD_MAX_ROWS_DEFAULT,
|
SbtDefaults.CARDS_AOD_MAX_ROWS_DEFAULT,
|
||||||
SbtDefaults.CARDS_AOD_MAX_ICONS_PER_ROW_DEFAULT,
|
SbtDefaults.CARDS_AOD_MAX_ICONS_PER_ROW_DEFAULT,
|
||||||
SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT,
|
SbtDefaults.CARDS_AOD_EVEN_DISTRIBUTION_DEFAULT,
|
||||||
SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT);
|
SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT);
|
||||||
}
|
}
|
||||||
return KeySet.cards(
|
return KeySet.cards(
|
||||||
SbtSettings.KEY_CARDS_LOCK_MAX_ROWS,
|
SbtSettings.KEY_CARDS_LOCK_MAX_ROWS,
|
||||||
SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW,
|
SbtSettings.KEY_CARDS_LOCK_MAX_ICONS_PER_ROW,
|
||||||
SbtSettings.KEY_CARDS_LOCK_EVEN_DISTRIBUTION,
|
SbtSettings.KEY_CARDS_LOCK_EVEN_DISTRIBUTION,
|
||||||
SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
||||||
|
SbtSettings.KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ROWS_DEFAULT,
|
SbtDefaults.CARDS_LOCK_MAX_ROWS_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT,
|
SbtDefaults.CARDS_LOCK_MAX_ICONS_PER_ROW_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT,
|
SbtDefaults.CARDS_LOCK_EVEN_DISTRIBUTION_DEFAULT,
|
||||||
SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT);
|
SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static KeySet iconKeys(
|
private static KeySet iconKeys(
|
||||||
@@ -390,12 +408,14 @@ final class LayoutSectionCopySupport {
|
|||||||
String autoNearest,
|
String autoNearest,
|
||||||
String middleSide,
|
String middleSide,
|
||||||
String verticalOffset,
|
String verticalOffset,
|
||||||
|
String iconHeight,
|
||||||
boolean enabledDefault,
|
boolean enabledDefault,
|
||||||
int countDefault,
|
int countDefault,
|
||||||
String positionDefault,
|
String positionDefault,
|
||||||
boolean autoNearestDefault,
|
boolean autoNearestDefault,
|
||||||
String middleSideDefault,
|
String middleSideDefault,
|
||||||
int verticalOffsetDefault
|
int verticalOffsetDefault,
|
||||||
|
int iconHeightDefault
|
||||||
) {
|
) {
|
||||||
return new KeySet(
|
return new KeySet(
|
||||||
enabled,
|
enabled,
|
||||||
@@ -403,12 +423,14 @@ final class LayoutSectionCopySupport {
|
|||||||
autoNearest,
|
autoNearest,
|
||||||
middleSide,
|
middleSide,
|
||||||
verticalOffset,
|
verticalOffset,
|
||||||
|
iconHeight,
|
||||||
count,
|
count,
|
||||||
enabledDefault,
|
enabledDefault,
|
||||||
positionDefault,
|
positionDefault,
|
||||||
autoNearestDefault,
|
autoNearestDefault,
|
||||||
middleSideDefault,
|
middleSideDefault,
|
||||||
verticalOffsetDefault,
|
verticalOffsetDefault,
|
||||||
|
iconHeightDefault,
|
||||||
countDefault);
|
countDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,12 +559,14 @@ final class LayoutSectionCopySupport {
|
|||||||
final String autoNearest;
|
final String autoNearest;
|
||||||
final String middleSide;
|
final String middleSide;
|
||||||
final String verticalOffset;
|
final String verticalOffset;
|
||||||
|
final String iconHeight;
|
||||||
final String count;
|
final String count;
|
||||||
final boolean enabledDefault;
|
final boolean enabledDefault;
|
||||||
final String positionDefault;
|
final String positionDefault;
|
||||||
final boolean autoNearestDefault;
|
final boolean autoNearestDefault;
|
||||||
final String middleSideDefault;
|
final String middleSideDefault;
|
||||||
final int verticalOffsetDefault;
|
final int verticalOffsetDefault;
|
||||||
|
final int iconHeightDefault;
|
||||||
final int countDefault;
|
final int countDefault;
|
||||||
final String maxRows;
|
final String maxRows;
|
||||||
final String maxIcons;
|
final String maxIcons;
|
||||||
@@ -566,18 +590,53 @@ final class LayoutSectionCopySupport {
|
|||||||
String middleSideDefault,
|
String middleSideDefault,
|
||||||
int verticalOffsetDefault,
|
int verticalOffsetDefault,
|
||||||
int countDefault
|
int countDefault
|
||||||
|
) {
|
||||||
|
this(
|
||||||
|
enabled,
|
||||||
|
position,
|
||||||
|
autoNearest,
|
||||||
|
middleSide,
|
||||||
|
verticalOffset,
|
||||||
|
null,
|
||||||
|
count,
|
||||||
|
enabledDefault,
|
||||||
|
positionDefault,
|
||||||
|
autoNearestDefault,
|
||||||
|
middleSideDefault,
|
||||||
|
verticalOffsetDefault,
|
||||||
|
0,
|
||||||
|
countDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeySet(
|
||||||
|
String enabled,
|
||||||
|
String position,
|
||||||
|
String autoNearest,
|
||||||
|
String middleSide,
|
||||||
|
String verticalOffset,
|
||||||
|
String iconHeight,
|
||||||
|
String count,
|
||||||
|
boolean enabledDefault,
|
||||||
|
String positionDefault,
|
||||||
|
boolean autoNearestDefault,
|
||||||
|
String middleSideDefault,
|
||||||
|
int verticalOffsetDefault,
|
||||||
|
int iconHeightDefault,
|
||||||
|
int countDefault
|
||||||
) {
|
) {
|
||||||
this.enabled = enabled;
|
this.enabled = enabled;
|
||||||
this.position = position;
|
this.position = position;
|
||||||
this.autoNearest = autoNearest;
|
this.autoNearest = autoNearest;
|
||||||
this.middleSide = middleSide;
|
this.middleSide = middleSide;
|
||||||
this.verticalOffset = verticalOffset;
|
this.verticalOffset = verticalOffset;
|
||||||
|
this.iconHeight = iconHeight;
|
||||||
this.count = count;
|
this.count = count;
|
||||||
this.enabledDefault = enabledDefault;
|
this.enabledDefault = enabledDefault;
|
||||||
this.positionDefault = positionDefault;
|
this.positionDefault = positionDefault;
|
||||||
this.autoNearestDefault = autoNearestDefault;
|
this.autoNearestDefault = autoNearestDefault;
|
||||||
this.middleSideDefault = middleSideDefault;
|
this.middleSideDefault = middleSideDefault;
|
||||||
this.verticalOffsetDefault = verticalOffsetDefault;
|
this.verticalOffsetDefault = verticalOffsetDefault;
|
||||||
|
this.iconHeightDefault = iconHeightDefault;
|
||||||
this.countDefault = countDefault;
|
this.countDefault = countDefault;
|
||||||
this.maxRows = null;
|
this.maxRows = null;
|
||||||
this.maxIcons = null;
|
this.maxIcons = null;
|
||||||
@@ -594,13 +653,16 @@ final class LayoutSectionCopySupport {
|
|||||||
String maxIcons,
|
String maxIcons,
|
||||||
String evenDistribution,
|
String evenDistribution,
|
||||||
String limitWidth,
|
String limitWidth,
|
||||||
|
String iconHeight,
|
||||||
int maxRowsDefault,
|
int maxRowsDefault,
|
||||||
int maxIconsDefault,
|
int maxIconsDefault,
|
||||||
boolean evenDistributionDefault,
|
boolean evenDistributionDefault,
|
||||||
boolean limitWidthDefault
|
boolean limitWidthDefault,
|
||||||
|
int iconHeightDefault
|
||||||
) {
|
) {
|
||||||
return new KeySet(maxRows, maxIcons, evenDistribution, limitWidth,
|
return new KeySet(maxRows, maxIcons, evenDistribution, limitWidth,
|
||||||
maxRowsDefault, maxIconsDefault, evenDistributionDefault, limitWidthDefault);
|
iconHeight, maxRowsDefault, maxIconsDefault,
|
||||||
|
evenDistributionDefault, limitWidthDefault, iconHeightDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeySet(
|
private KeySet(
|
||||||
@@ -608,22 +670,26 @@ final class LayoutSectionCopySupport {
|
|||||||
String maxIcons,
|
String maxIcons,
|
||||||
String evenDistribution,
|
String evenDistribution,
|
||||||
String limitWidth,
|
String limitWidth,
|
||||||
|
String iconHeight,
|
||||||
int maxRowsDefault,
|
int maxRowsDefault,
|
||||||
int maxIconsDefault,
|
int maxIconsDefault,
|
||||||
boolean evenDistributionDefault,
|
boolean evenDistributionDefault,
|
||||||
boolean limitWidthDefault
|
boolean limitWidthDefault,
|
||||||
|
int iconHeightDefault
|
||||||
) {
|
) {
|
||||||
this.enabled = null;
|
this.enabled = null;
|
||||||
this.position = null;
|
this.position = null;
|
||||||
this.autoNearest = null;
|
this.autoNearest = null;
|
||||||
this.middleSide = null;
|
this.middleSide = null;
|
||||||
this.verticalOffset = null;
|
this.verticalOffset = null;
|
||||||
|
this.iconHeight = iconHeight;
|
||||||
this.count = null;
|
this.count = null;
|
||||||
this.enabledDefault = false;
|
this.enabledDefault = false;
|
||||||
this.positionDefault = null;
|
this.positionDefault = null;
|
||||||
this.autoNearestDefault = false;
|
this.autoNearestDefault = false;
|
||||||
this.middleSideDefault = null;
|
this.middleSideDefault = null;
|
||||||
this.verticalOffsetDefault = 0;
|
this.verticalOffsetDefault = 0;
|
||||||
|
this.iconHeightDefault = iconHeightDefault;
|
||||||
this.countDefault = 0;
|
this.countDefault = 0;
|
||||||
this.maxRows = maxRows;
|
this.maxRows = maxRows;
|
||||||
this.maxIcons = maxIcons;
|
this.maxIcons = maxIcons;
|
||||||
|
|||||||
@@ -174,6 +174,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
SbtDefaults.LAYOUT_STATUS_MIDDLE_AUTO_NEAREST_SIDE_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(),
|
||||||
|
SbtDefaults.LAYOUT_STATUS_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
LayoutSectionCopySupport.Section.STATUS,
|
LayoutSectionCopySupport.Section.STATUS,
|
||||||
false,
|
false,
|
||||||
refresh));
|
refresh));
|
||||||
@@ -205,6 +207,10 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
SbtDefaults.LAYOUT_NOTIF_MIDDLE_AUTO_NEAREST_SIDE_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
|
||||||
|
? SbtDefaults.LAYOUT_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT
|
||||||
|
: SbtDefaults.LAYOUT_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
LayoutSectionCopySupport.Section.NOTIFICATIONS_ICONS,
|
LayoutSectionCopySupport.Section.NOTIFICATIONS_ICONS,
|
||||||
false,
|
false,
|
||||||
refresh));
|
refresh));
|
||||||
@@ -309,6 +315,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
boolean autoNearestDefault,
|
boolean autoNearestDefault,
|
||||||
String middleSideDefault,
|
String middleSideDefault,
|
||||||
int verticalOffsetDefault,
|
int verticalOffsetDefault,
|
||||||
|
String iconHeightKey,
|
||||||
|
int iconHeightDefault,
|
||||||
LayoutSectionCopySupport.Section copySection,
|
LayoutSectionCopySupport.Section copySection,
|
||||||
boolean cardsMode,
|
boolean cardsMode,
|
||||||
@Nullable Runnable refresh
|
@Nullable Runnable refresh
|
||||||
@@ -346,6 +354,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
middleSideDefault,
|
middleSideDefault,
|
||||||
indexedSceneKey(base + "_vertical_offset_px", 0),
|
indexedSceneKey(base + "_vertical_offset_px", 0),
|
||||||
verticalOffsetDefault,
|
verticalOffsetDefault,
|
||||||
|
iconHeightKey,
|
||||||
|
iconHeightDefault,
|
||||||
legacyEnabledKey,
|
legacyEnabledKey,
|
||||||
countKey,
|
countKey,
|
||||||
count,
|
count,
|
||||||
@@ -381,6 +391,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
indexedSceneKey(base + "_vertical_offset_px", i),
|
indexedSceneKey(base + "_vertical_offset_px", i),
|
||||||
verticalOffsetDefault,
|
verticalOffsetDefault,
|
||||||
null,
|
null,
|
||||||
|
0,
|
||||||
|
null,
|
||||||
null,
|
null,
|
||||||
count,
|
count,
|
||||||
null));
|
null));
|
||||||
@@ -440,6 +452,8 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
String middleSideDefault,
|
String middleSideDefault,
|
||||||
String verticalOffsetKey,
|
String verticalOffsetKey,
|
||||||
int verticalOffsetDefault,
|
int verticalOffsetDefault,
|
||||||
|
@Nullable String iconHeightKey,
|
||||||
|
int iconHeightDefault,
|
||||||
@Nullable String legacyEnabledKey,
|
@Nullable String legacyEnabledKey,
|
||||||
@Nullable String countKey,
|
@Nullable String countKey,
|
||||||
int count,
|
int count,
|
||||||
@@ -453,6 +467,18 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
sectionContent.addView(
|
sectionContent.addView(
|
||||||
iconContainerCountControl(context, prefs, countKey, legacyEnabledKey, count, onCountChanged),
|
iconContainerCountControl(context, prefs, countKey, legacyEnabledKey, count, onCountChanged),
|
||||||
insertIndex);
|
insertIndex);
|
||||||
|
if (iconHeightKey != null) {
|
||||||
|
sectionContent.addView(
|
||||||
|
sizeStepper(
|
||||||
|
context,
|
||||||
|
prefs,
|
||||||
|
R.string.layout_icon_height_steps,
|
||||||
|
iconHeightKey,
|
||||||
|
iconHeightDefault,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX),
|
||||||
|
Math.min(insertIndex + 1, sectionContent.getChildCount()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
updateIconCardTitle(card, titleId, index, count);
|
updateIconCardTitle(card, titleId, index, count);
|
||||||
bindXmlPositionSection(
|
bindXmlPositionSection(
|
||||||
@@ -623,6 +649,16 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
R.string.label_limit_screen_width,
|
R.string.label_limit_screen_width,
|
||||||
aod ? SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH : SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
aod ? SbtSettings.KEY_CARDS_AOD_LIMIT_TO_WIDTH : SbtSettings.KEY_CARDS_LOCK_LIMIT_TO_WIDTH,
|
||||||
aod ? SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT : SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT));
|
aod ? SbtDefaults.CARDS_AOD_LIMIT_TO_WIDTH_DEFAULT : SbtDefaults.CARDS_LOCK_LIMIT_TO_WIDTH_DEFAULT));
|
||||||
|
content.addView(sizeStepper(
|
||||||
|
context,
|
||||||
|
prefs,
|
||||||
|
R.string.layout_icon_height_steps,
|
||||||
|
aod ? SbtSettings.KEY_CARDS_AOD_ICON_HEIGHT_STEPS : SbtSettings.KEY_CARDS_LOCK_ICON_HEIGHT_STEPS,
|
||||||
|
aod
|
||||||
|
? SbtDefaults.LAYOUT_CARDS_NOTIF_AOD_ICON_HEIGHT_STEPS_DEFAULT
|
||||||
|
: SbtDefaults.LAYOUT_CARDS_NOTIF_LOCK_ICON_HEIGHT_STEPS_DEFAULT,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MIN,
|
||||||
|
SbtDefaults.LAYOUT_ICON_HEIGHT_STEPS_MAX));
|
||||||
return card(context, R.string.layout_notification_position_title, content);
|
return card(context, R.string.layout_notification_position_title, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,6 +891,23 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private View stepper(Context context, SharedPreferences prefs, int label, String key, int def, int min, int max) {
|
private View stepper(Context context, SharedPreferences prefs, int label, String key, int def, int min, int max) {
|
||||||
|
return stepper(context, prefs, label, key, def, min, max, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private View sizeStepper(Context context, SharedPreferences prefs, int label, String key, int def, int min, int max) {
|
||||||
|
return stepper(context, prefs, label, key, def, min, max, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private View stepper(
|
||||||
|
Context context,
|
||||||
|
SharedPreferences prefs,
|
||||||
|
int label,
|
||||||
|
String key,
|
||||||
|
int def,
|
||||||
|
int min,
|
||||||
|
int max,
|
||||||
|
boolean showDefaultButton
|
||||||
|
) {
|
||||||
LinearLayout outer = vertical(context);
|
LinearLayout outer = vertical(context);
|
||||||
outer.addView(body(context, label));
|
outer.addView(body(context, label));
|
||||||
LinearLayout row = new LinearLayout(context);
|
LinearLayout row = new LinearLayout(context);
|
||||||
@@ -862,11 +915,17 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
row.setGravity(Gravity.CENTER_VERTICAL);
|
row.setGravity(Gravity.CENTER_VERTICAL);
|
||||||
MaterialButton minus = button(context, "-");
|
MaterialButton minus = button(context, "-");
|
||||||
MaterialButton plus = button(context, "+");
|
MaterialButton plus = button(context, "+");
|
||||||
|
MaterialButton reset = showDefaultButton ? button(context, "D") : null;
|
||||||
EditText input = numericInput(context, true);
|
EditText input = numericInput(context, true);
|
||||||
input.setText(String.valueOf(clamp(prefs.getInt(key, def), min, max)));
|
input.setText(String.valueOf(clamp(prefs.getInt(key, def), min, max)));
|
||||||
row.addView(minus, buttonParams());
|
row.addView(minus, buttonParams());
|
||||||
row.addView(input, inputParams());
|
row.addView(input, inputParams());
|
||||||
row.addView(plus, buttonParams());
|
row.addView(plus, buttonParams());
|
||||||
|
if (reset != null) {
|
||||||
|
LinearLayout.LayoutParams resetParams = buttonParams();
|
||||||
|
resetParams.leftMargin = dp(8);
|
||||||
|
row.addView(reset, resetParams);
|
||||||
|
}
|
||||||
outer.addView(row);
|
outer.addView(row);
|
||||||
View.OnClickListener listener = view -> {
|
View.OnClickListener listener = view -> {
|
||||||
int delta = view == minus ? -1 : 1;
|
int delta = view == minus ? -1 : 1;
|
||||||
@@ -876,6 +935,13 @@ abstract class LockedSceneLayoutFragment extends Fragment {
|
|||||||
};
|
};
|
||||||
minus.setOnClickListener(listener);
|
minus.setOnClickListener(listener);
|
||||||
plus.setOnClickListener(listener);
|
plus.setOnClickListener(listener);
|
||||||
|
if (reset != null) {
|
||||||
|
reset.setOnClickListener(v -> {
|
||||||
|
int next = clamp(def, min, max);
|
||||||
|
input.setText(String.valueOf(next));
|
||||||
|
persistIntPref(prefs, key, next);
|
||||||
|
});
|
||||||
|
}
|
||||||
input.setOnFocusChangeListener((v, hasFocus) -> {
|
input.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
if (!hasFocus) {
|
if (!hasFocus) {
|
||||||
int next = clamp(parseInt(input, def), min, max);
|
int next = clamp(parseInt(input, def), min, max);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class SystemIconsFragment extends Fragment {
|
|||||||
"hotspot"),
|
"hotspot"),
|
||||||
new SystemIconEntry(R.string.system_icon_nfc,
|
new SystemIconEntry(R.string.system_icon_nfc,
|
||||||
new String[]{"stat_sys_nfc"},
|
new String[]{"stat_sys_nfc"},
|
||||||
android.R.drawable.ic_menu_share,
|
R.drawable.sbt_ic_nfc,
|
||||||
"nfc_on", "nfc"),
|
"nfc_on", "nfc"),
|
||||||
new SystemIconEntry(R.string.system_icon_vpn,
|
new SystemIconEntry(R.string.system_icon_vpn,
|
||||||
new String[]{"stat_sys_branded_vpn"},
|
new String[]{"stat_sys_branded_vpn"},
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M4,5h9c1.1,0 2,0.9 2,2v10c0,1.1 -0.9,2 -2,2H4c-1.1,0 -2,-0.9 -2,-2V7c0,-1.1 0.9,-2 2,-2zM4,7v10h9V7H4z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M17.2,7.2c1.3,1.2 2.1,2.9 2.1,4.8s-0.8,3.6 -2.1,4.8l-1.1,-1.2c1,-0.9 1.6,-2.2 1.6,-3.6s-0.6,-2.7 -1.6,-3.6l1.1,-1.2z" />
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFFFF"
|
||||||
|
android:pathData="M20.1,4.4C22,6.3 23,9 23,12s-1,5.7 -2.9,7.6l-1.2,-1.2c1.6,-1.6 2.5,-3.8 2.5,-6.4s-0.9,-4.8 -2.5,-6.4l1.2,-1.2z" />
|
||||||
|
</vector>
|
||||||
@@ -70,6 +70,12 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/debug_visualize_camera_cutout" />
|
android:text="@string/debug_visualize_camera_cutout" />
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/debug_visualize_aod_stock_containers_switch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/debug_visualize_aod_stock_containers" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,15 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:textAppearance="?attr/textAppearanceCaption" />
|
android:textAppearance="?attr/textAppearanceCaption" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/hidden_item_last_seen"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textAppearance="?attr/textAppearanceCaption"
|
||||||
|
android:visibility="gone" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<string name="debug_visualize_clock_container">Clock container</string>
|
<string name="debug_visualize_clock_container">Clock container</string>
|
||||||
<string name="debug_visualize_chip_container">Status chip container</string>
|
<string name="debug_visualize_chip_container">Status chip container</string>
|
||||||
<string name="debug_visualize_camera_cutout">Camera cutout</string>
|
<string name="debug_visualize_camera_cutout">Camera cutout</string>
|
||||||
|
<string name="debug_visualize_aod_stock_containers">AOD stock containers and derived statusbar</string>
|
||||||
<string name="debug_section_systemui">SystemUI</string>
|
<string name="debug_section_systemui">SystemUI</string>
|
||||||
<string name="debug_restart_systemui">Restart SystemUI</string>
|
<string name="debug_restart_systemui">Restart SystemUI</string>
|
||||||
<string name="debug_restart_systemui_started">SystemUI restart requested.</string>
|
<string name="debug_restart_systemui_started">SystemUI restart requested.</string>
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
<string name="hidden_apps_close">Close</string>
|
<string name="hidden_apps_close">Close</string>
|
||||||
<string name="hidden_apps_exception_regex_input_hint">Regex</string>
|
<string name="hidden_apps_exception_regex_input_hint">Regex</string>
|
||||||
<string name="hidden_apps_package_with_exceptions">%1$s \u2022 %2$d exceptions</string>
|
<string name="hidden_apps_package_with_exceptions">%1$s \u2022 %2$d exceptions</string>
|
||||||
|
<string name="hidden_apps_last_seen">Last seen: %1$s</string>
|
||||||
<string name="hidden_apps_default_modes_title">Default settings</string>
|
<string name="hidden_apps_default_modes_title">Default settings</string>
|
||||||
<string name="hidden_apps_add_exception">Add exception</string>
|
<string name="hidden_apps_add_exception">Add exception</string>
|
||||||
<string name="hidden_apps_delete_exception">Delete</string>
|
<string name="hidden_apps_delete_exception">Delete</string>
|
||||||
@@ -171,6 +173,8 @@
|
|||||||
<string name="layout_item_enabled">Enabled</string>
|
<string name="layout_item_enabled">Enabled</string>
|
||||||
<string name="layout_copy_from">Copy from</string>
|
<string name="layout_copy_from">Copy from</string>
|
||||||
<string name="layout_icon_container_count">Number of containers</string>
|
<string name="layout_icon_container_count">Number of containers</string>
|
||||||
|
<string name="layout_icon_height_steps">Icon height (% of statusbar)</string>
|
||||||
|
<string name="layout_chip_height_steps">Chip height (% of statusbar)</string>
|
||||||
<string name="layout_locked_notifications_title">Locked notifications mode</string>
|
<string name="layout_locked_notifications_title">Locked notifications mode</string>
|
||||||
<string name="layout_locked_notifications_hint">Mirrors the Samsung notification display style for AOD and lockscreen.</string>
|
<string name="layout_locked_notifications_hint">Mirrors the Samsung notification display style for AOD and lockscreen.</string>
|
||||||
<string name="layout_misc_title">Misc</string>
|
<string name="layout_misc_title">Misc</string>
|
||||||
|
|||||||
+83
@@ -155,6 +155,89 @@ public final class PackedStatusBarLayoutSolverTest {
|
|||||||
assertTrue(notifications.width() == 65.0);
|
assertTrue(notifications.width() == 65.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void singleIconGroupsKeepDotWhenChipConsumesSpace() {
|
||||||
|
ArrayList<LayoutItem> items = new ArrayList<>();
|
||||||
|
LayoutItem notifications = iconItem("Notifs", "Notifs", "notifications", 4, 30, 120, 0, 30);
|
||||||
|
LayoutItem status = iconItem("Status", "Status", "status", 4, 30, 120, 0, 30);
|
||||||
|
LayoutItem chip = LayoutItem.fixed("Chip", "Chip", Position.LEFT, Fallback.LEFT, 200, 30, 0);
|
||||||
|
items.add(notifications);
|
||||||
|
items.add(status);
|
||||||
|
items.add(chip);
|
||||||
|
|
||||||
|
PackedStatusBarLayoutSolver.solve(
|
||||||
|
new Spec(70, 0, 0, 0, new ArrayList<>(Arrays.asList("Notifs", "Status", "Chip"))),
|
||||||
|
items);
|
||||||
|
|
||||||
|
assertTrue(notifications.visibleIcons == 0);
|
||||||
|
assertTrue(notifications.dot);
|
||||||
|
assertTrue(notifications.width() > 0);
|
||||||
|
assertTrue(status.visibleIcons == 0);
|
||||||
|
assertTrue(status.dot);
|
||||||
|
assertTrue(status.width() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void groupEdgeDotIsNotCompactedAgainstNonIconNeighbor() {
|
||||||
|
ArrayList<LayoutItem> items = new ArrayList<>();
|
||||||
|
items.add(new LayoutItem(
|
||||||
|
"Clock",
|
||||||
|
"Clock",
|
||||||
|
Position.LEFT,
|
||||||
|
Fallback.LEFT,
|
||||||
|
LayoutItem.boxes(
|
||||||
|
new Box(102, 14, 33, 38),
|
||||||
|
new Box(0, 32, 134, 47))));
|
||||||
|
LayoutItem status = iconItem("Status", "Status", "status", 4, 27, 108, 39, 36);
|
||||||
|
status.direction = PackedStatusBarLayoutSolver.Direction.LEFT;
|
||||||
|
LayoutItem chip = LayoutItem.fixed("Chip", "Chip", Position.LEFT, Fallback.LEFT, 200, 44, 33);
|
||||||
|
LayoutItem notifications = iconItem("Notifs", "Notifs", "notifications", 4, 27, 108, 36, 36);
|
||||||
|
notifications.direction = PackedStatusBarLayoutSolver.Direction.RIGHT;
|
||||||
|
items.add(status);
|
||||||
|
items.add(chip);
|
||||||
|
items.add(notifications);
|
||||||
|
|
||||||
|
PackedStatusBarLayoutSolver.solve(
|
||||||
|
productionSpec(834, 387, 59, 0),
|
||||||
|
items);
|
||||||
|
|
||||||
|
assertTrue(status.visibleIcons == 0);
|
||||||
|
assertTrue(status.dot);
|
||||||
|
assertTrue(status.width() == 27.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void finalIconGroupKeepsDotWhenChipConsumesAllRemainingSpaceBeforeCutout() {
|
||||||
|
ArrayList<LayoutItem> items = new ArrayList<>();
|
||||||
|
items.add(new LayoutItem(
|
||||||
|
"Clock",
|
||||||
|
"Clock",
|
||||||
|
Position.LEFT,
|
||||||
|
Fallback.LEFT,
|
||||||
|
LayoutItem.boxes(
|
||||||
|
new Box(102, 14, 33, 38),
|
||||||
|
new Box(0, 32, 134, 47))));
|
||||||
|
LayoutItem status = iconItem("Status", "Status", "status", 4, 24, 96, 39, 32);
|
||||||
|
status.direction = PackedStatusBarLayoutSolver.Direction.LEFT;
|
||||||
|
LayoutItem chip = LayoutItem.fixed("Chip", "Chip", Position.LEFT, Fallback.LEFT, 397, 44, 33);
|
||||||
|
LayoutItem notifications = iconItem("Notifs", "Notifs", "notifications", 4, 29, 116, 36, 39);
|
||||||
|
notifications.direction = PackedStatusBarLayoutSolver.Direction.RIGHT;
|
||||||
|
notifications.compactDotWidth = 27;
|
||||||
|
items.add(status);
|
||||||
|
items.add(chip);
|
||||||
|
items.add(notifications);
|
||||||
|
|
||||||
|
PackedStatusBarLayoutSolver.solve(
|
||||||
|
productionSpec(834, 387, 59, 0),
|
||||||
|
items);
|
||||||
|
|
||||||
|
assertTrue(notifications.visibleIcons == 0);
|
||||||
|
assertTrue(notifications.dot);
|
||||||
|
assertTrue(notifications.width() > 0);
|
||||||
|
assertTrue(notifications.right() <= 387);
|
||||||
|
assertTrue(chip.right() <= notifications.left());
|
||||||
|
}
|
||||||
|
|
||||||
private static Spec cutoutSpec() {
|
private static Spec cutoutSpec() {
|
||||||
return new Spec(
|
return new Spec(
|
||||||
1200,
|
1200,
|
||||||
|
|||||||
+36
@@ -66,6 +66,42 @@ public final class UnlockedLayoutBandTest {
|
|||||||
assertEquals("icon4", band.placements.get(2).key);
|
assertEquals("icon4", band.placements.get(2).key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clippedStatusChipRendersAtClippedSourceWidthInsteadOfCroppingScaledBitmap() {
|
||||||
|
ArrayList<SnapshotPlacement> placements = new ArrayList<>();
|
||||||
|
placements.add(new SnapshotPlacement(
|
||||||
|
null,
|
||||||
|
new Bounds(181, 26, 417, 59),
|
||||||
|
"chip",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
0xffffffff,
|
||||||
|
null,
|
||||||
|
new Bounds(0, 7, 397, 44),
|
||||||
|
0,
|
||||||
|
new Bounds(181, 26, 417, 59)));
|
||||||
|
UnlockedLayoutBand band = UnlockedLayoutBand.icons(
|
||||||
|
LayoutItemKind.CHIP,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
placements,
|
||||||
|
LayoutPosition.LEFT,
|
||||||
|
false,
|
||||||
|
AnchorSide.LEFT,
|
||||||
|
false);
|
||||||
|
|
||||||
|
band.prepareForSide(AnchorSide.RIGHT, "normal");
|
||||||
|
band.applyPackedContinuousWidth(211, AnchorSide.RIGHT);
|
||||||
|
band.place(182);
|
||||||
|
|
||||||
|
assertEquals(1, band.placements.size());
|
||||||
|
SnapshotPlacement chip = band.placements.get(0);
|
||||||
|
assertEquals(231, chip.bounds.width);
|
||||||
|
assertEquals(211, chip.contentBounds.width);
|
||||||
|
assertEquals(211, chip.sourceRenderBounds.width);
|
||||||
|
assertEquals(0, chip.sourceOffsetX);
|
||||||
|
}
|
||||||
|
|
||||||
private static ArrayList<SnapshotPlacement> placements(int count, int width, int height) {
|
private static ArrayList<SnapshotPlacement> placements(int count, int width, int height) {
|
||||||
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
ArrayList<SnapshotPlacement> result = new ArrayList<>();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user