Use Taskbar window for phones (only works on gesture nav) with flag

* Try to avoid re-creating TaskbarActivityContext to
avoid re-inflating taskbar views
* Toggle via Flipper App (key 1101)
OR adb shell setprop persist.wm.debug.hide_navbar_window 1 && adb reboot
TODOs
* Only works for gesture nav, not 3 button
* Sampling on phone doesn't always work.

Bug: 219035565
Change-Id: I2a015f99d5f1fe86d7261eec9fd898bd4480ff9f
This commit is contained in:
Vinit Nayak
2022-06-08 14:01:02 -07:00
parent 4eec22f818
commit 7db37b3d94
8 changed files with 147 additions and 43 deletions

View File

@@ -263,6 +263,7 @@
<dimen name="taskbar_contextual_buttons_size">35dp</dimen>
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
<dimen name="taskbar_stashed_small_screen">108dp</dimen>
<dimen name="taskbar_unstash_input_area">316dp</dimen>
<dimen name="taskbar_stashed_handle_height">4dp</dimen>
<dimen name="taskbar_edu_wave_anim_trans_y">25dp</dimen>

View File

@@ -15,6 +15,8 @@
*/
package com.android.launcher3.taskbar;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
@@ -25,6 +27,7 @@ import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.RevealOutlineAnimation;
@@ -55,9 +58,9 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
private final TaskbarActivityContext mActivity;
private final SharedPreferences mPrefs;
private final StashedHandleView mStashedHandleView;
private final int mStashedHandleWidth;
private int mStashedHandleWidth;
private final int mStashedHandleHeight;
private final RegionSamplingHelper mRegionSamplingHelper;
private RegionSamplingHelper mRegionSamplingHelper;
private final MultiValueAlpha mTaskbarStashedHandleAlpha;
private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
this::updateStashedHandleHintScale);
@@ -85,30 +88,27 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
false /* animate */);
final Resources resources = mActivity.getResources();
mStashedHandleWidth = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
mStashedHandleHeight = resources.getDimensionPixelSize(
R.dimen.taskbar_stashed_handle_height);
mRegionSamplingHelper = new RegionSamplingHelper(mStashedHandleView,
new RegionSamplingHelper.SamplingCallback() {
@Override
public void onRegionDarknessChanged(boolean isRegionDark) {
mStashedHandleView.updateHandleColor(isRegionDark, true /* animate */);
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY,
isRegionDark).apply();
}
@Override
public Rect getSampledRegion(View sampledView) {
return mStashedHandleView.getSampledRegion();
}
}, Executors.UI_HELPER_EXECUTOR);
}
public void init(TaskbarControllers controllers) {
mControllers = controllers;
mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
Resources resources = mActivity.getResources();
if (isPhoneMode(mActivity.getDeviceProfile())) {
mStashedHandleView.getLayoutParams().height =
resources.getDimensionPixelSize(R.dimen.taskbar_size);
mStashedHandleWidth =
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
} else {
mStashedHandleView.getLayoutParams().height = deviceProfile.taskbarSize;
mStashedHandleWidth =
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
}
mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(0);
mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(
isPhoneMode(deviceProfile) ? 1 : 0);
mTaskbarStashedHandleHintScale.updateValue(1f);
final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
@@ -135,10 +135,33 @@ public class StashedHandleViewController implements TaskbarControllers.LoggableT
view.setPivotX(stashedCenterX);
view.setPivotY(stashedCenterY);
});
initRegionSampler();
if (isPhoneMode(deviceProfile)) {
onIsStashedChanged(true);
}
}
private void initRegionSampler() {
mRegionSamplingHelper = new RegionSamplingHelper(mStashedHandleView,
new RegionSamplingHelper.SamplingCallback() {
@Override
public void onRegionDarknessChanged(boolean isRegionDark) {
mStashedHandleView.updateHandleColor(isRegionDark, true /* animate */);
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY,
isRegionDark).apply();
}
@Override
public Rect getSampledRegion(View sampledView) {
return mStashedHandleView.getSampledRegion();
}
}, Executors.UI_HELPER_EXECUTOR);
}
public void onDestroy() {
mRegionSamplingHelper.stopAndDestroy();
mRegionSamplingHelper = null;
}
public MultiValueAlpha getStashedHandleAlpha() {

View File

@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW;
import static com.android.launcher3.testing.shared.ResourceUtils.getBoolByName;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
@@ -130,6 +131,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
// The flag to know if the window is excluded from magnification region computation.
private boolean mIsExcludeFromMagnificationRegion = false;
private boolean mBindingItems = false;
private boolean mAddedWindow = false;
private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
@@ -218,7 +221,12 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
mControllers.init(sharedState);
updateSysuiStateFlags(sharedState.sysuiStateFlags, true /* fromInit */);
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
if (!mAddedWindow) {
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
mAddedWindow = true;
} else {
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
}
@Override
@@ -461,7 +469,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
mIsDestroyed = true;
setUIController(TaskbarUIController.DEFAULT);
mControllers.onDestroy();
mWindowManager.removeViewImmediate(mDragLayer);
if (!FLAG_HIDE_NAVBAR_WINDOW) {
mWindowManager.removeViewImmediate(mDragLayer);
mAddedWindow = false;
}
}
public void updateSysuiStateFlags(int systemUiStateFlags, boolean fromInit) {
@@ -596,6 +607,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
* Returns the default height of the window, including the static corner radii above taskbar.
*/
public int getDefaultTaskbarWindowHeight() {
if (FLAG_HIDE_NAVBAR_WINDOW && mDeviceProfile.isPhone) {
return getResources().getDimensionPixelSize(R.dimen.taskbar_stashed_size);
}
return mDeviceProfile.taskbarSize + Math.max(getLeftCornerRadius(), getRightCornerRadius());
}

View File

@@ -86,8 +86,14 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
}
}
protected void onDestroy(boolean forceDestroy) {
if (forceDestroy) {
ViewTreeObserverWrapper.removeOnComputeInsetsListener(mTaskbarInsetsComputer);
}
}
protected void onDestroy() {
ViewTreeObserverWrapper.removeOnComputeInsetsListener(mTaskbarInsetsComputer);
onDestroy(!TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW);
}
@Override
@@ -101,7 +107,7 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
onDestroy();
onDestroy(true);
}
@Override

View File

@@ -30,6 +30,7 @@ import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Handler;
import android.os.SystemProperties;
import android.provider.Settings;
import android.view.Display;
@@ -58,6 +59,9 @@ import java.io.PrintWriter;
*/
public class TaskbarManager {
public static final boolean FLAG_HIDE_NAVBAR_WINDOW =
SystemProperties.getBoolean("persist.wm.debug.hide_navbar_window", false);
private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
@@ -147,7 +151,7 @@ public class TaskbarManager {
} else {
// Config change might be handled without re-creating the taskbar
if (mTaskbarActivityContext != null) {
if (dp != null && dp.isTaskbarPresent) {
if (dp != null && isTaskbarPresent(dp)) {
mTaskbarActivityContext.updateDeviceProfile(dp);
}
mTaskbarActivityContext.onConfigurationChanged(configDiff);
@@ -159,7 +163,8 @@ public class TaskbarManager {
@Override
public void onLowMemory() { }
};
mShutdownReceiver = new SimpleBroadcastReceiver(i -> destroyExistingTaskbar());
mShutdownReceiver = new SimpleBroadcastReceiver(i ->
destroyExistingTaskbar());
mDispInfoChangeListener = (context, info, flags) -> {
if ((flags & CHANGE_FLAGS) != 0) {
recreateTaskbar();
@@ -179,7 +184,9 @@ public class TaskbarManager {
private void destroyExistingTaskbar() {
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.onDestroy();
mTaskbarActivityContext = null;
if (!FLAG_HIDE_NAVBAR_WINDOW) {
mTaskbarActivityContext = null;
}
}
}
@@ -260,24 +267,32 @@ public class TaskbarManager {
}
}
/**
* This method is called multiple times (ex. initial init, then when user unlocks) in which case
* we fully want to destroy an existing taskbar and create a new one.
* In other case (folding/unfolding) we don't need to remove and add window.
*/
private void recreateTaskbar() {
DeviceProfile dp = mUserUnlocked ?
LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
destroyExistingTaskbar();
DeviceProfile dp =
mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
boolean isTaskBarEnabled = dp != null && dp.isTaskbarPresent;
boolean isTaskBarEnabled = dp != null && isTaskbarPresent(dp);
if (!isTaskBarEnabled) {
SystemUiProxy.INSTANCE.get(mContext)
.notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
return;
}
mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController,
mUnfoldProgressProvider);
if (mTaskbarActivityContext == null) {
mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController,
mUnfoldProgressProvider);
} else {
mTaskbarActivityContext.updateDeviceProfile(dp);
}
mTaskbarActivityContext.init(mSharedState);
if (mActivity != null) {
mTaskbarActivityContext.setUIController(
createTaskbarUIControllerForActivity(mActivity));
@@ -301,6 +316,18 @@ public class TaskbarManager {
}
}
/**
* @return {@code true} if provided device profile isn't a large screen profile
* and we are using a single window for taskbar and navbar.
*/
public static boolean isPhoneMode(DeviceProfile deviceProfile) {
return TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW && deviceProfile.isPhone;
}
private boolean isTaskbarPresent(DeviceProfile deviceProfile) {
return FLAG_HIDE_NAVBAR_WINDOW || deviceProfile.isTaskbarPresent;
}
public void onRotationProposal(int rotation, boolean isValid) {
if (mTaskbarActivityContext != null) {
mTaskbarActivityContext.onRotationProposal(rotation, isValid);

View File

@@ -20,6 +20,7 @@ import static android.view.HapticFeedbackConstants.LONG_PRESS;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
import static com.android.launcher3.taskbar.Utilities.appendFlag;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SWITCHER_SHOWING;
@@ -30,6 +31,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.Nullable;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.util.Log;
import android.view.View;
import android.view.ViewConfiguration;
@@ -38,6 +40,7 @@ import androidx.annotation.NonNull;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -69,6 +72,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible.
public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
public static final int FLAG_STASHED_SMALL_SCREEN = 1 << 9; // phone screen gesture nav, stashed
// If any of these flags are enabled, isInApp should return true.
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
@@ -76,7 +80,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_APP_ALL_APPS;
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_APP_ALL_APPS |
FLAG_STASHED_SMALL_SCREEN;
private static final int FLAGS_STASHED_IN_APP_IGNORING_IME =
FLAGS_STASHED_IN_APP & ~FLAG_STASHED_IN_APP_IME;
@@ -166,15 +171,25 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
return (inApp && stashedInApp) || (!inApp && stashedLauncherState);
boolean stashedForSmallScreen = hasAnyFlag(flags, FLAG_STASHED_SMALL_SCREEN);
return (inApp && stashedInApp) || (!inApp && stashedLauncherState)
|| stashedForSmallScreen;
});
public TaskbarStashController(TaskbarActivityContext activity) {
mActivity = activity;
mPrefs = Utilities.getPrefs(mActivity);
mSystemUiProxy = SystemUiProxy.INSTANCE.get(activity);
mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
mStashedHeight = mActivity.getDeviceProfile().stashedTaskbarSize;
if (isPhoneMode(mActivity.getDeviceProfile())) {
// DeviceProfile's taskbar vars aren't initialized w/ the flag off
Resources resources = mActivity.getResources();
mUnstashedHeight = resources.getDimensionPixelSize(R.dimen.taskbar_size);
mStashedHeight = resources.getDimensionPixelOffset(R.dimen.taskbar_stashed_size);
} else {
mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
mStashedHeight = mActivity.getDeviceProfile().stashedTaskbarSize;
}
}
public void init(TaskbarControllers controllers, boolean setupUIVisible) {
@@ -202,6 +217,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
updateStateForFlag(FLAG_STASHED_SMALL_SCREEN, isPhoneMode(mActivity.getDeviceProfile()));
applyState();
notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
@@ -212,7 +228,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* state.
*/
public boolean supportsVisualStashing() {
return mControllers.uiController.supportsVisualStashing();
return mControllers.uiController.supportsVisualStashing() ||
isPhoneMode(mActivity.getDeviceProfile());
}
/**
@@ -266,7 +283,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* Returns whether the taskbar should be stashed in the current LauncherState.
*/
public boolean isInStashedLauncherState() {
return hasAnyFlag(FLAG_IN_STASHED_LAUNCHER_STATE) && supportsVisualStashing();
return (hasAnyFlag(FLAG_IN_STASHED_LAUNCHER_STATE) && supportsVisualStashing());
}
private boolean hasAnyFlag(int flagMask) {
@@ -295,6 +312,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
* @see WindowInsets.Type#systemBars()
*/
public int getContentHeightToReportToApps() {
if (isPhoneMode(mActivity.getDeviceProfile())) {
return getStashedHeight();
}
if (supportsVisualStashing() && hasAnyFlag(FLAGS_REPORT_STASHED_INSETS_TO_APP)) {
DeviceProfile dp = mActivity.getDeviceProfile();
if (hasAnyFlag(FLAG_STASHED_IN_APP_SETUP) && dp.isTaskbarPresent && !dp.isLandscape) {
@@ -410,11 +431,18 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
}
mAnimator = new AnimatorSet();
addJankMonitorListener(mAnimator, /* appearing= */ !mIsStashed);
final float stashTranslation = isPhoneMode(mActivity.getDeviceProfile()) ? 0 :
(mUnstashedHeight - mStashedHeight) / 2f;
if (!supportsVisualStashing()) {
// Just hide/show the icons and background instead of stashing into a handle.
mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1)
.setDuration(duration));
mAnimator.playTogether(mTaskbarBackgroundOffset.animateToValue(isStashed ? 1 : 0)
.setDuration(duration));
mAnimator.playTogether(mIconTranslationYForStash.animateToValue(isStashed ?
stashTranslation : 0)
.setDuration(duration));
mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
mAnimator.setStartDelay(startDelay);
@@ -438,7 +466,6 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
if (isStashed) {
firstHalfDurationScale = 0.75f;
secondHalfDurationScale = 0.5f;
final float stashTranslation = (mUnstashedHeight - mStashedHeight) / 2f;
fullLengthAnimatorSet.play(mIconTranslationYForStash.animateToValue(stashTranslation));
if (animateBg) {
@@ -450,7 +477,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
firstHalfAnimatorSet.playTogether(
mIconAlphaForStash.animateToValue(0),
mIconScaleForStash.animateToValue(STASHED_TASKBAR_SCALE)
mIconScaleForStash.animateToValue(isPhoneMode(mActivity.getDeviceProfile()) ?
0 : STASHED_TASKBAR_SCALE)
);
secondHalfAnimatorSet.playTogether(
mTaskbarStashedHandleAlpha.animateToValue(1)

View File

@@ -20,6 +20,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
import static com.android.quickstep.AnimatedFloat.VALUE;
import android.annotation.NonNull;
@@ -35,6 +36,7 @@ import androidx.core.view.OneShotPreDrawListener;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
@@ -108,7 +110,9 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
public void init(TaskbarControllers controllers) {
mControllers = controllers;
mTaskbarView.init(new TaskbarViewCallbacks());
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
mTaskbarView.getLayoutParams().height = isPhoneMode(mActivity.getDeviceProfile())
? mActivity.getResources().getDimensionPixelSize(R.dimen.taskbar_size)
: mActivity.getDeviceProfile().taskbarSize;
mThemeIconsColor = ThemedIconDrawable.getColors(mTaskbarView.getContext())[0];
mTaskbarIconScaleForStash.updateValue(1f);

View File

@@ -38,6 +38,7 @@ import android.view.Surface;
import com.android.launcher3.CellLayout.ContainerType;
import com.android.launcher3.DevicePaddings.DevicePadding;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.DotRenderer;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.IconNormalizer;