Handling statusbar color when back navigation (1/2)

Introduce SystemBarCustomizer so BackAnimationController could customize
the status bar color according the background color when back animation
is in progress.

Bug: 259491355
Test: manual
Change-Id: I967ec4555a94b270d91f498639140cb7d81dd266
This commit is contained in:
Arthur Hung
2023-01-05 15:16:44 +00:00
parent 11b6d46951
commit 0a6ab4fe2a
11 changed files with 203 additions and 17 deletions

View File

@@ -52,4 +52,10 @@ public interface BackAnimation {
* @param progressThreshold the max threshold to keep progressing back animation.
*/
void setSwipeThresholds(float triggerThreshold, float progressThreshold);
/**
* Sets the system bar listener to control the system bar color.
* @param customizer the controller to control system bar color.
*/
void setStatusBarCustomizer(StatusBarCustomizer customizer);
}

View File

@@ -17,11 +17,17 @@
package com.android.wm.shell.back;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static com.android.wm.shell.back.BackAnimationConstants.UPDATE_SYSUI_FLAGS_THRESHOLD;
import android.annotation.NonNull;
import android.graphics.Color;
import android.graphics.Rect;
import android.view.SurfaceControl;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.view.AppearanceRegion;
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
/**
@@ -29,18 +35,35 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
*/
public class BackAnimationBackground {
private static final int BACKGROUND_LAYER = -1;
private static final int NO_APPEARANCE = 0;
private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer;
private SurfaceControl mBackgroundSurface;
private StatusBarCustomizer mCustomizer;
private boolean mIsRequestingStatusBarAppearance;
private boolean mBackgroundIsDark;
private Rect mStartBounds;
public BackAnimationBackground(RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer) {
mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer;
}
void ensureBackground(int color, @NonNull SurfaceControl.Transaction transaction) {
/**
* Ensures the back animation background color layer is present.
* @param startRect The start bounds of the closing target.
* @param color The background color.
* @param transaction The animation transaction.
*/
void ensureBackground(Rect startRect, int color,
@NonNull SurfaceControl.Transaction transaction) {
if (mBackgroundSurface != null) {
return;
}
mBackgroundIsDark = ColorUtils.calculateLuminance(color) < 0.5f;
final float[] colorComponents = new float[] { Color.red(color) / 255.f,
Color.green(color) / 255.f, Color.blue(color) / 255.f };
@@ -54,6 +77,8 @@ public class BackAnimationBackground {
transaction.setColor(mBackgroundSurface, colorComponents)
.setLayer(mBackgroundSurface, BACKGROUND_LAYER)
.show(mBackgroundSurface);
mStartBounds = startRect;
mIsRequestingStatusBarAppearance = false;
}
void removeBackground(@NonNull SurfaceControl.Transaction transaction) {
@@ -65,5 +90,31 @@ public class BackAnimationBackground {
transaction.remove(mBackgroundSurface);
}
mBackgroundSurface = null;
mIsRequestingStatusBarAppearance = false;
}
void setStatusBarCustomizer(StatusBarCustomizer customizer) {
mCustomizer = customizer;
}
void onBackProgressed(float progress) {
if (mCustomizer == null || mStartBounds.isEmpty()) {
return;
}
final boolean shouldCustomizeSystemBar = progress > UPDATE_SYSUI_FLAGS_THRESHOLD;
if (shouldCustomizeSystemBar == mIsRequestingStatusBarAppearance) {
return;
}
mIsRequestingStatusBarAppearance = shouldCustomizeSystemBar;
if (mIsRequestingStatusBarAppearance) {
final AppearanceRegion region = new AppearanceRegion(!mBackgroundIsDark
? APPEARANCE_LIGHT_STATUS_BARS : NO_APPEARANCE,
mStartBounds);
mCustomizer.customizeStatusBarAppearance(region);
} else {
mCustomizer.customizeStatusBarAppearance(null);
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.back;
/**
* The common constant values used in back animators.
*/
class BackAnimationConstants {
static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.20f;
static final float PROGRESS_COMMIT_THRESHOLD = 0.1f;
}

View File

@@ -55,6 +55,7 @@ import android.window.IOnBackInvokedCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.AppearanceRegion;
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
@@ -142,6 +143,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
});
private final BackAnimationBackground mAnimationBackground;
private StatusBarCustomizer mCustomizer;
public BackAnimationController(
@NonNull ShellInit shellInit,
@@ -268,6 +270,12 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mShellExecutor.execute(() -> BackAnimationController.this.setSwipeThresholds(
triggerThreshold, progressThreshold));
}
@Override
public void setStatusBarCustomizer(StatusBarCustomizer customizer) {
mCustomizer = customizer;
mAnimationBackground.setStatusBarCustomizer(customizer);
}
}
private static class IBackAnimationImpl extends IBackAnimation.Stub
@@ -294,12 +302,23 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
BackNavigationInfo.TYPE_RETURN_TO_HOME));
}
public void customizeStatusBarAppearance(AppearanceRegion appearance) {
executeRemoteCallWithTaskPermission(mController, "useLauncherSysBarFlags",
(controller) -> controller.customizeStatusBarAppearance(appearance));
}
@Override
public void invalidate() {
mController = null;
}
}
private void customizeStatusBarAppearance(AppearanceRegion appearance) {
if (mCustomizer != null) {
mCustomizer.customizeStatusBarAppearance(appearance);
}
}
void registerAnimation(@BackNavigationInfo.BackTargetType int type,
@NonNull BackAnimationRunner runner) {
mAnimationDefinition.set(type, runner);

View File

@@ -19,6 +19,7 @@ package com.android.wm.shell.back;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static com.android.wm.shell.back.BackAnimationConstants.PROGRESS_COMMIT_THRESHOLD;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
import android.animation.Animator;
@@ -89,7 +90,6 @@ class CrossActivityAnimation {
private static final float WINDOW_X_SHIFT_DP = 96;
private static final int SCALE_FACTOR = 100;
// TODO(b/264710590): Use the progress commit threshold from ViewConfiguration once it exists.
private static final float PROGRESS_COMMIT_THRESHOLD = 0.1f;
private static final float TARGET_COMMIT_PROGRESS = 0.5f;
private static final float ENTER_ALPHA_THRESHOLD = 0.22f;
@@ -184,7 +184,7 @@ class CrossActivityAnimation {
mStartTaskRect.offsetTo(0, 0);
// Draw background with task background color.
mBackground.ensureBackground(
mBackground.ensureBackground(mClosingTarget.windowConfiguration.getBounds(),
mEnteringTarget.taskInfo.taskDescription.getBackgroundColor(), mTransaction);
}
@@ -244,6 +244,7 @@ class CrossActivityAnimation {
: mapLinear(progress, 0, 1f, 0, TARGET_COMMIT_PROGRESS)) * SCALE_FACTOR;
mLeavingProgressSpring.animateToFinalPosition(springProgress);
mEnteringProgressSpring.animateToFinalPosition(springProgress);
mBackground.onBackProgressed(progress);
}
private void onGestureCommitted() {

View File

@@ -141,7 +141,8 @@ class CrossTaskBackAnimation {
mStartTaskRect.offsetTo(0, 0);
// Draw background.
mBackground.ensureBackground(BACKGROUNDCOLOR, mTransaction);
mBackground.ensureBackground(mClosingTarget.windowConfiguration.getBounds(),
BACKGROUNDCOLOR, mTransaction);
}
private void updateGestureBackProgress(float progress, BackEvent event) {
@@ -189,6 +190,8 @@ class CrossTaskBackAnimation {
applyColorTransform(mClosingTarget.leash, closingColorScale);
applyTransform(mEnteringTarget.leash, mEnteringCurrentRect, mCornerRadius);
mTransaction.apply();
mBackground.onBackProgressed(progress);
}
private void updatePostCommitClosingAnimation(float progress) {

View File

@@ -150,9 +150,11 @@ class CustomizeActivityAnimation {
// Draw background with task background color.
if (mEnteringTarget.taskInfo != null && mEnteringTarget.taskInfo.taskDescription != null) {
mBackground.ensureBackground(mNextBackgroundColor == Color.TRANSPARENT
? mEnteringTarget.taskInfo.taskDescription.getBackgroundColor()
: mNextBackgroundColor, mTransaction);
mBackground.ensureBackground(mClosingTarget.windowConfiguration.getBounds(),
mNextBackgroundColor == Color.TRANSPARENT
? mEnteringTarget.taskInfo.taskDescription.getBackgroundColor()
: mNextBackgroundColor,
mTransaction);
}
}

View File

@@ -16,8 +16,9 @@
package com.android.wm.shell.back;
import android.window.IOnBackInvokedCallback;
import com.android.internal.view.AppearanceRegion;
import android.view.IRemoteAnimationRunner;
import android.window.IOnBackInvokedCallback;
/**
* Interface for Launcher process to register back invocation callbacks.
@@ -34,4 +35,9 @@ interface IBackAnimation {
* Clears the previously registered {@link IOnBackInvokedCallback}.
*/
void clearBackToLauncherCallback();
/**
* Uses launcher flags to update the system bar color.
*/
void customizeStatusBarAppearance(in AppearanceRegion appearance);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.back;
import com.android.internal.view.AppearanceRegion;
/**
* Interface to customize the system bar color.
*/
public interface StatusBarCustomizer {
/**
* Called when the status bar color needs to be changed.
* @param appearance The region of appearance.
*/
void customizeStatusBarAppearance(AppearanceRegion appearance);
}

View File

@@ -82,6 +82,7 @@ import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.tracing.ProtoTracer;
import com.android.systemui.tracing.nano.EdgeBackGestureHandlerProto;
import com.android.systemui.tracing.nano.SystemUiTraceProto;
@@ -207,6 +208,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private final Provider<BackGestureTfClassifierProvider>
mBackGestureTfClassifierProviderProvider;
private final FeatureFlags mFeatureFlags;
private final Provider<LightBarController> mLightBarControllerProvider;
// The left side edge width where touch down is allowed
private int mEdgeWidthLeft;
@@ -352,7 +354,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
FalsingManager falsingManager,
Provider<NavigationBarEdgePanel> navigationBarEdgePanelProvider,
Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider,
FeatureFlags featureFlags) {
FeatureFlags featureFlags,
Provider<LightBarController> lightBarControllerProvider) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = executor;
@@ -372,6 +375,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mNavBarEdgePanelProvider = navigationBarEdgePanelProvider;
mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
mFeatureFlags = featureFlags;
mLightBarControllerProvider = lightBarControllerProvider;
mLastReportedConfig.setTo(mContext.getResources().getConfiguration());
ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
@@ -1055,6 +1059,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
if (DEBUG_MISSING_GESTURE) {
Log.d(DEBUG_MISSING_GESTURE_TAG, "Update display size: mDisplaySize=" + mDisplaySize);
}
if (mEdgeBackPlugin != null) {
mEdgeBackPlugin.setDisplaySize(mDisplaySize);
}
@@ -1148,6 +1153,13 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
public void setBackAnimation(BackAnimation backAnimation) {
mBackAnimation = backAnimation;
updateBackAnimationThresholds();
if (mLightBarControllerProvider.get() != null) {
mBackAnimation.setStatusBarCustomizer((appearance) -> {
mMainExecutor.execute(() ->
mLightBarControllerProvider.get()
.customizeStatusBarAppearance(appearance));
});
}
}
/**
@@ -1175,6 +1187,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
private final Provider<BackGestureTfClassifierProvider>
mBackGestureTfClassifierProviderProvider;
private final FeatureFlags mFeatureFlags;
private final Provider<LightBarController> mLightBarControllerProvider;
@Inject
public Factory(OverviewProxyService overviewProxyService,
@@ -1194,7 +1207,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
Provider<NavigationBarEdgePanel> navBarEdgePanelProvider,
Provider<BackGestureTfClassifierProvider>
backGestureTfClassifierProviderProvider,
FeatureFlags featureFlags) {
FeatureFlags featureFlags,
Provider<LightBarController> lightBarControllerProvider) {
mOverviewProxyService = overviewProxyService;
mSysUiState = sysUiState;
mPluginManager = pluginManager;
@@ -1212,6 +1226,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mNavBarEdgePanelProvider = navBarEdgePanelProvider;
mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
mFeatureFlags = featureFlags;
mLightBarControllerProvider = lightBarControllerProvider;
}
/** Construct a {@link EdgeBackGestureHandler}. */
@@ -1234,7 +1249,8 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
mFalsingManager,
mNavBarEdgePanelProvider,
mBackGestureTfClassifierProviderProvider,
mFeatureFlags);
mFeatureFlags,
mLightBarControllerProvider);
}
}

View File

@@ -88,6 +88,8 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private boolean mDirectReplying;
private boolean mNavbarColorManagedByIme;
private boolean mIsCustomizingForBackNav;
@Inject
public LightBarController(
Context ctx,
@@ -137,16 +139,17 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
}
if (stackAppearancesChanged || sbModeChanged) {
if (stackAppearancesChanged || sbModeChanged || mIsCustomizingForBackNav) {
mAppearanceRegions = appearanceRegions;
onStatusBarModeChanged(statusBarMode);
mIsCustomizingForBackNav = false;
}
mNavbarColorManagedByIme = navbarColorManagedByIme;
}
void onStatusBarModeChanged(int newBarMode) {
mStatusBarMode = newBarMode;
updateStatus();
updateStatus(mAppearanceRegions);
}
public void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
@@ -185,6 +188,31 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
reevaluate();
}
/**
* Controls the light status bar temporarily for back navigation.
* @param appearance the custmoized appearance.
*/
public void customizeStatusBarAppearance(AppearanceRegion appearance) {
if (appearance != null) {
final ArrayList<AppearanceRegion> appearancesList = new ArrayList<>();
appearancesList.add(appearance);
for (int i = 0; i < mAppearanceRegions.length; i++) {
final AppearanceRegion ar = mAppearanceRegions[i];
if (appearance.getBounds().contains(ar.getBounds())) {
continue;
}
appearancesList.add(ar);
}
final AppearanceRegion[] newAppearances = new AppearanceRegion[appearancesList.size()];
updateStatus(appearancesList.toArray(newAppearances));
mIsCustomizingForBackNav = true;
} else {
mIsCustomizingForBackNav = false;
updateStatus(mAppearanceRegions);
}
}
/**
* Sets whether the direct-reply is in use or not.
* @param directReplying {@code true} when the direct-reply is in-use.
@@ -226,12 +254,12 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
&& unlockMode != BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
}
private void updateStatus() {
final int numStacks = mAppearanceRegions.length;
private void updateStatus(AppearanceRegion[] appearanceRegions) {
final int numStacks = appearanceRegions.length;
final ArrayList<Rect> lightBarBounds = new ArrayList<>();
for (int i = 0; i < numStacks; i++) {
final AppearanceRegion ar = mAppearanceRegions[i];
final AppearanceRegion ar = appearanceRegions[i];
if (isLight(ar.getAppearance(), mStatusBarMode, APPEARANCE_LIGHT_STATUS_BARS)) {
lightBarBounds.add(ar.getBounds());
}
@@ -247,7 +275,6 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
else if (lightBarBounds.size() == numStacks) {
mStatusBarIconController.setIconsDarkArea(null);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
// Not the same for every stack, magic!