Mirror stock statusbar transitions
This commit is contained in:
+163
-6
@@ -13,6 +13,7 @@ import android.service.notification.StatusBarNotification;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -189,6 +190,7 @@ final class StockLayoutCanvasController {
|
||||
private int notificationDrawerCloseGeneration;
|
||||
private boolean notificationDrawerClosePending;
|
||||
private int aodVisualAlphaGeneration;
|
||||
private int systemBarRequestedVisibleTypes = WindowInsets.Type.statusBars();
|
||||
|
||||
StockLayoutCanvasController(RuntimeContext runtimeContext) {
|
||||
this.runtimeContext = runtimeContext;
|
||||
@@ -217,10 +219,44 @@ final class StockLayoutCanvasController {
|
||||
statusIconModelTracker.installHooks(classLoader);
|
||||
installShadeExpansionHooks(classLoader);
|
||||
installShadeHeaderAnimationGuardHook(classLoader);
|
||||
installSystemBarAttributeListener(classLoader);
|
||||
installViewRootHook(classLoader);
|
||||
hooksInstalled = true;
|
||||
}
|
||||
|
||||
private void installSystemBarAttributeListener(ClassLoader classLoader) {
|
||||
Class<?> commandQueueClass = ReflectionSupport.findClassIfExists(
|
||||
"com.android.systemui.statusbar.CommandQueue",
|
||||
classLoader);
|
||||
if (commandQueueClass == null) {
|
||||
return;
|
||||
}
|
||||
XposedHookSupport.hookAllMethodsIfExists(
|
||||
runtimeContext.getFramework(),
|
||||
commandQueueClass,
|
||||
"onSystemBarAttributesChanged",
|
||||
chain -> {
|
||||
Object result = chain.proceed();
|
||||
updateSystemBarRequestedVisibleTypes(chain.getArgs());
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private void updateSystemBarRequestedVisibleTypes(List<Object> args) {
|
||||
if (args == null || args.size() <= 5) {
|
||||
return;
|
||||
}
|
||||
Integer displayId = asInteger(args.get(0));
|
||||
Integer requestedVisibleTypes = asInteger(args.get(5));
|
||||
if (displayId == null || displayId != 0 || requestedVisibleTypes == null) {
|
||||
return;
|
||||
}
|
||||
if (systemBarRequestedVisibleTypes == requestedVisibleTypes) {
|
||||
return;
|
||||
}
|
||||
systemBarRequestedVisibleTypes = requestedVisibleTypes;
|
||||
}
|
||||
|
||||
private void installNotificationCollectionHooks(ClassLoader classLoader) {
|
||||
for (String className : List.of(
|
||||
"com.android.systemui.statusbar.notification.collection.NotifCollection",
|
||||
@@ -428,7 +464,11 @@ final class StockLayoutCanvasController {
|
||||
rememberAodPluginVisualAlpha(view, alpha);
|
||||
}
|
||||
}
|
||||
return chain.proceed();
|
||||
Object result = chain.proceed();
|
||||
if (target instanceof View view) {
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "setVisibility", chain -> {
|
||||
Object target = chain.getThisObject();
|
||||
@@ -444,6 +484,7 @@ final class StockLayoutCanvasController {
|
||||
Object result = chain.proceed();
|
||||
if (target instanceof View view && visibilityArg instanceof Integer visibility) {
|
||||
scheduleStatusChipRefreshIfContentChanged(view);
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
@@ -455,7 +496,11 @@ final class StockLayoutCanvasController {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return chain.proceed();
|
||||
Object result = chain.proceed();
|
||||
if (target instanceof View view) {
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "setTranslationX", chain -> {
|
||||
Object target = chain.getThisObject();
|
||||
@@ -465,7 +510,11 @@ final class StockLayoutCanvasController {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return chain.proceed();
|
||||
Object result = chain.proceed();
|
||||
if (target instanceof View view) {
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
XposedHookSupport.hookAllMethodsIfExists(runtimeContext.getFramework(), viewClass, "layout", chain -> {
|
||||
Object target = chain.getThisObject();
|
||||
@@ -482,15 +531,21 @@ final class StockLayoutCanvasController {
|
||||
right,
|
||||
bottom);
|
||||
if (override != null) {
|
||||
return chain.proceed(new Object[]{
|
||||
Object result = chain.proceed(new Object[]{
|
||||
override.left,
|
||||
override.top,
|
||||
override.right,
|
||||
override.bottom
|
||||
});
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return chain.proceed();
|
||||
Object result = chain.proceed();
|
||||
if (target instanceof View view) {
|
||||
syncUnlockedHostsFromStockStatusBar(view);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2137,6 +2192,83 @@ final class StockLayoutCanvasController {
|
||||
debugBoundsOverlayController.bringToFront(root);
|
||||
}
|
||||
|
||||
private void syncUnlockedHostsFromStockStatusBar(View view) {
|
||||
if (!isPhoneStatusBarRoot(view)) {
|
||||
return;
|
||||
}
|
||||
View root = unlockedStatusBarRootWithUnlockedHostsFor(view);
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
syncUnlockedHostsToStockStatusBar(
|
||||
root,
|
||||
runtimeContext.getModeStateRepository().getActiveScene());
|
||||
}
|
||||
|
||||
private void syncUnlockedHostsToStockStatusBar(View root, SceneKey activeScene) {
|
||||
if (root == null || !hasDirectUnlockedLayoutHost(root)) {
|
||||
return;
|
||||
}
|
||||
if (activeScene == null || !activeScene.isUnlocked()) {
|
||||
ownedIconHostManager.setUnlockedHostsTransform(root, 1f, 0f, 0f);
|
||||
return;
|
||||
}
|
||||
View stockStatusBar = phoneStatusBarRootIn(root);
|
||||
if (stockStatusBar == null || stockStatusBar == root) {
|
||||
ownedIconHostManager.setUnlockedHostsTransform(root, 1f, 0f, 0f);
|
||||
return;
|
||||
}
|
||||
float alpha = stockStatusBar.getVisibility() == View.VISIBLE
|
||||
? clampAlpha(stockStatusBar.getAlpha())
|
||||
: 0f;
|
||||
float translationX = stockStatusBar.getLeft() + stockStatusBar.getTranslationX();
|
||||
float translationY = stockStatusBar.getTop() + stockStatusBar.getTranslationY();
|
||||
ownedIconHostManager.setUnlockedHostsTransform(
|
||||
root,
|
||||
alpha,
|
||||
translationX,
|
||||
translationY);
|
||||
}
|
||||
|
||||
private View unlockedStatusBarRootWithUnlockedHostsFor(View view) {
|
||||
View current = view;
|
||||
while (current != null) {
|
||||
if (isUnlockedStatusBarRoot(current) && hasDirectUnlockedLayoutHost(current)) {
|
||||
return current;
|
||||
}
|
||||
Object parent = current.getParent();
|
||||
current = parent instanceof View parentView ? parentView : null;
|
||||
}
|
||||
View root = view.getRootView();
|
||||
return isUnlockedStatusBarRoot(root) && hasDirectUnlockedLayoutHost(root) ? root : null;
|
||||
}
|
||||
|
||||
private View phoneStatusBarRootIn(View root) {
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
if (isPhoneStatusBarRoot(root)) {
|
||||
return root;
|
||||
}
|
||||
if (!(root instanceof ViewGroup group)) {
|
||||
return null;
|
||||
}
|
||||
ArrayDeque<View> queue = new ArrayDeque<>();
|
||||
queue.add(group);
|
||||
while (!queue.isEmpty()) {
|
||||
View current = queue.removeFirst();
|
||||
if (current != root && isPhoneStatusBarRoot(current)) {
|
||||
return current;
|
||||
}
|
||||
if (current instanceof ViewGroup childGroup) {
|
||||
for (int i = 0; i < childGroup.getChildCount(); i++) {
|
||||
queue.addLast(childGroup.getChildAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void applyToRootInternal(View root) {
|
||||
if (root == null) {
|
||||
return;
|
||||
@@ -2249,11 +2381,14 @@ final class StockLayoutCanvasController {
|
||||
activeScene,
|
||||
rootDirty,
|
||||
lockedCarrierTextSource());
|
||||
boolean shouldShowUnlockedHosts = unlockedScene || aodScene || renderResult.shouldOwnLockscreen();
|
||||
boolean shouldShowUnlockedHosts = unlockedScene
|
||||
|| aodScene
|
||||
|| (!unlockedScene && renderResult.shouldOwnLockscreen());
|
||||
ownedIconHostManager.setUnlockedHostsVisible(root, shouldShowUnlockedHosts);
|
||||
if (shouldShowUnlockedHosts) {
|
||||
bringUnlockedHostsAndDebugOverlayToFront(root);
|
||||
}
|
||||
syncUnlockedHostsToStockStatusBar(root, activeScene);
|
||||
syncAodOwnedHostVisualState(root, unlockedHosts);
|
||||
}
|
||||
}
|
||||
@@ -2353,6 +2488,17 @@ final class StockLayoutCanvasController {
|
||||
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_AOD_CARDS_NOTIFICATION_HOST) != null;
|
||||
}
|
||||
|
||||
private boolean hasDirectUnlockedLayoutHost(View root) {
|
||||
if (!(root instanceof ViewGroup group)) {
|
||||
return false;
|
||||
}
|
||||
return findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_STATUS_HOST) != null
|
||||
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_NOTIFICATION_HOST) != null
|
||||
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CLOCK_HOST) != null
|
||||
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CARRIER_HOST) != null
|
||||
|| findDirectOwnedHost(group, OwnedIconHostManager.TAG_UNLOCKED_CHIP_HOST) != null;
|
||||
}
|
||||
|
||||
private boolean hasLockscreenCardsNotificationHost(View root) {
|
||||
return root instanceof ViewGroup group
|
||||
&& findDirectOwnedHost(
|
||||
@@ -3388,6 +3534,9 @@ final class StockLayoutCanvasController {
|
||||
|| ongoingPrivacyChipInRoot(view) == null) {
|
||||
return false;
|
||||
}
|
||||
if (alpha <= 0f && !statusBarsRequestedVisible()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3402,6 +3551,14 @@ final class StockLayoutCanvasController {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean statusBarsRequestedVisible() {
|
||||
return (systemBarRequestedVisibleTypes & WindowInsets.Type.statusBars()) != 0;
|
||||
}
|
||||
|
||||
private static Integer asInteger(Object value) {
|
||||
return value instanceof Integer integer ? integer : null;
|
||||
}
|
||||
|
||||
private boolean isPhoneStatusBarRoot(View view) {
|
||||
return view != null
|
||||
&& view.getClass().getName().contains("PhoneStatusBarView");
|
||||
|
||||
@@ -119,6 +119,17 @@ public final class OwnedIconHostManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void setUnlockedHostsTransform(
|
||||
View root,
|
||||
float alpha,
|
||||
float translationX,
|
||||
float translationY
|
||||
) {
|
||||
for (String tag : UNLOCKED_HOST_ORDER) {
|
||||
setHostTransform(root, tag, alpha, translationX, translationY);
|
||||
}
|
||||
}
|
||||
|
||||
public void bringUnlockedHostsToFront(View root) {
|
||||
if (!(root instanceof ViewGroup parent)) {
|
||||
return;
|
||||
@@ -169,6 +180,31 @@ public final class OwnedIconHostManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void setHostTransform(
|
||||
View root,
|
||||
String tag,
|
||||
float alpha,
|
||||
float translationX,
|
||||
float translationY
|
||||
) {
|
||||
if (!(root instanceof ViewGroup parent) || tag == null) {
|
||||
return;
|
||||
}
|
||||
FrameLayout host = findDirectHost(parent, tag);
|
||||
if (host == null) {
|
||||
return;
|
||||
}
|
||||
if (host.getAlpha() != alpha) {
|
||||
host.setAlpha(alpha);
|
||||
}
|
||||
if (host.getTranslationX() != translationX) {
|
||||
host.setTranslationX(translationX);
|
||||
}
|
||||
if (host.getTranslationY() != translationY) {
|
||||
host.setTranslationY(translationY);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<View> unlockedHosts(ViewGroup parent) {
|
||||
ArrayList<View> hosts = new ArrayList<>();
|
||||
for (String tag : UNLOCKED_HOST_ORDER) {
|
||||
|
||||
Reference in New Issue
Block a user