From c87f7c74ef6265fa0d19a8a5019b0eedab6e9d40 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 14 Jun 2023 16:01:02 -0700 Subject: [PATCH] Simplifying taskbar recreation logic Using the same config changes as used by the Launcher activity to avoid any inconsistencies Bug: 269409332 Test: Tentative fix, can't reproduce the original bug Flag: N/A Change-Id: I3d7503cf13e6b3112151f1db520486d87871584c --- .../taskbar/TaskbarActivityContext.java | 85 ++++++----- .../launcher3/taskbar/TaskbarManager.java | 132 +++++++----------- 2 files changed, 88 insertions(+), 129 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index 6fddd4b5e9..4d7eb63110 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -49,7 +49,6 @@ import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.os.Process; -import android.os.SystemProperties; import android.os.Trace; import android.provider.Settings; import android.util.Log; @@ -128,8 +127,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { private static final String IME_DRAWS_IME_NAV_BAR_RES_NAME = "config_imeDrawsImeNavBar"; - private static final boolean ENABLE_THREE_BUTTON_TASKBAR = - SystemProperties.getBoolean("persist.debug.taskbar_three_button", false); private static final String TAG = "TaskbarActivityContext"; private static final String WINDOW_TITLE = "Taskbar"; @@ -169,30 +166,27 @@ public class TaskbarActivityContext extends BaseTaskbarContext { TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider unfoldTransitionProgressProvider) { super(windowContext); + + applyDeviceProfile(launcherDp); + final Resources resources = getResources(); - matchDeviceProfile(launcherDp, getResources()); - - mNavMode = DisplayController.getNavigationMode(windowContext); mImeDrawsImeNavBar = getBoolByName(IME_DRAWS_IME_NAV_BAR_RES_NAME, resources, false); mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", () -> getPackageManager().isSafeMode()); + + // TODO(b/244231596) For shared Taskbar window, update this value in applyDeviceProfile() + // instead so to get correct value when recreating the taskbar SettingsCache settingsCache = SettingsCache.INSTANCE.get(this); mIsUserSetupComplete = settingsCache.getValue( Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE), 0); - mIsNavBarForceVisible = settingsCache.getValue( - Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0); - - // TODO(b/244231596) For shared Taskbar window, update this value in init() instead so - // to get correct value when recreating the taskbar mIsNavBarKidsMode = settingsCache.getValue( Settings.Secure.getUriFor(Settings.Secure.NAV_BAR_KIDS_MODE), 0); + mIsNavBarForceVisible = mIsNavBarKidsMode; // Get display and corners first, as views might use them in constructor. Display display = windowContext.getDisplay(); - Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY - ? windowContext.getApplicationContext() - : windowContext.getApplicationContext().createDisplayContext(display); + Context c = getApplicationContext(); mWindowManager = c.getSystemService(WindowManager.class); mLeftCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT); mRightCorner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT); @@ -267,6 +261,38 @@ public class TaskbarActivityContext extends BaseTaskbarContext { bubbleControllersOptional); } + /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ + public void updateDeviceProfile(DeviceProfile launcherDp) { + applyDeviceProfile(launcherDp); + + mControllers.taskbarOverlayController.updateLauncherDeviceProfile(launcherDp); + AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE); + // Reapply fullscreen to take potential new screen size into account. + setTaskbarWindowFullscreen(mIsFullscreen); + + dispatchDeviceProfileChanged(); + } + + /** + * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update + * the icon size + */ + private void applyDeviceProfile(DeviceProfile originDeviceProfile) { + mDeviceProfile = originDeviceProfile.toBuilder(this) + .withDimensionsOverride(deviceProfile -> { + // Taskbar should match the number of icons of hotseat + deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons; + // Same QSB width to have a smooth animation + deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth; + + // Update icon size + deviceProfile.iconSizePx = deviceProfile.taskbarIconSize; + deviceProfile.updateIconSize(1f, getResources()); + }).build(); + mNavMode = DisplayController.getNavigationMode(this); + } + + public void init(@NonNull TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); mWindowLayoutParams = @@ -308,19 +334,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { return mDeviceProfile; } - /** Updates {@link DeviceProfile} instances for any Taskbar windows. */ - public void updateDeviceProfile(DeviceProfile launcherDp, NavigationMode navMode) { - mNavMode = navMode; - mControllers.taskbarOverlayController.updateLauncherDeviceProfile(launcherDp); - matchDeviceProfile(launcherDp, getResources()); - - AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE); - // Reapply fullscreen to take potential new screen size into account. - setTaskbarWindowFullscreen(mIsFullscreen); - - dispatchDeviceProfileChanged(); - } - @Override public void dispatchDeviceProfileChanged() { super.dispatchDeviceProfileChanged(); @@ -328,24 +341,6 @@ public class TaskbarActivityContext extends BaseTaskbarContext { getDeviceProfile().toSmallString()); } - /** - * Copy the original DeviceProfile, match the number of hotseat icons and qsb width and update - * the icon size - */ - private void matchDeviceProfile(DeviceProfile originDeviceProfile, Resources resources) { - mDeviceProfile = originDeviceProfile.toBuilder(this) - .withDimensionsOverride(deviceProfile -> { - // Taskbar should match the number of icons of hotseat - deviceProfile.numShownHotseatIcons = originDeviceProfile.numShownHotseatIcons; - // Same QSB width to have a smooth animation - deviceProfile.hotseatQsbWidth = originDeviceProfile.hotseatQsbWidth; - - // Update icon size - deviceProfile.iconSizePx = deviceProfile.taskbarIconSize; - deviceProfile.updateIconSize(1f, resources); - }).build(); - } - /** * Returns the View bounds of transient taskbar. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index 38d34fde6b..8f3898f345 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -22,8 +22,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING; import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING_KEY; -import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY; -import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE; import static com.android.launcher3.util.DisplayController.TASKBAR_NOT_DESTROYED_TAG; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.launcher3.util.FlagDebugUtils.formatFlagChange; @@ -51,6 +49,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.anim.AnimatorPlaybackController; @@ -58,8 +57,6 @@ import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter; -import com.android.launcher3.util.DisplayController; -import com.android.launcher3.util.NavigationMode; import com.android.launcher3.util.SettingsCache; import com.android.launcher3.util.SimpleBroadcastReceiver; import com.android.quickstep.RecentsActivity; @@ -79,6 +76,22 @@ public class TaskbarManager { private static final String TAG = "TaskbarManager"; private static final boolean DEBUG = false; + /** + * All the configurations which do not initiate taskbar recreation. + * This includes all the configurations defined in Launcher's manifest entry and + * ActivityController#filterConfigChanges + */ + private static final int SKIP_RECREATE_CONFIG_CHANGES = ActivityInfo.CONFIG_WINDOW_CONFIGURATION + | ActivityInfo.CONFIG_KEYBOARD + | ActivityInfo.CONFIG_KEYBOARD_HIDDEN + | ActivityInfo.CONFIG_MCC + | ActivityInfo.CONFIG_MNC + | ActivityInfo.CONFIG_NAVIGATION + | ActivityInfo.CONFIG_ORIENTATION + | ActivityInfo.CONFIG_SCREEN_SIZE + | ActivityInfo.CONFIG_SCREEN_LAYOUT + | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; + public static final boolean FLAG_HIDE_NAVBAR_WINDOW = SystemProperties.getBoolean("persist.wm.debug.hide_navbar_window", false); @@ -89,12 +102,11 @@ public class TaskbarManager { Settings.Secure.NAV_BAR_KIDS_MODE); private final Context mContext; - private final DisplayController mDisplayController; private final TaskbarNavButtonController mNavButtonController; - private final SettingsCache.OnChangeListener mUserSetupCompleteListener; - private final SettingsCache.OnChangeListener mNavBarKidsModeListener; private final ComponentCallbacks mComponentCallbacks; - private final SimpleBroadcastReceiver mShutdownReceiver; + + private final SimpleBroadcastReceiver mShutdownReceiver = + new SimpleBroadcastReceiver(i -> destroyExistingTaskbar()); // The source for this provider is set when Launcher is available // We use 'non-destroyable' version here so the original provider won't be destroyed @@ -102,7 +114,6 @@ public class TaskbarManager { // It's destruction/creation will be managed by the activity. private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider = new NonDestroyableScopedUnfoldTransitionProgressProvider(); - private NavigationMode mNavMode; private TaskbarActivityContext mTaskbarActivityContext; private StatefulActivity mActivity; @@ -113,19 +124,11 @@ public class TaskbarManager { private final TaskbarSharedState mSharedState = new TaskbarSharedState(); /** - * We use WindowManager's ComponentCallbacks() for most of the config changes, however for - * navigation mode, that callback gets called too soon, before it's internal navigation mode - * reflects the current one. - * DisplayController's callback is delayed enough to get the correct nav mode value - * - * We also use density change here because DeviceProfile has had a chance to update it's state - * whereas density for component callbacks registered in this class don't update DeviceProfile. - * Confused? Me too. Make it less confusing (TODO: b/227669780) - * - * Flags used with {@link #mDispInfoChangeListener} + * We use WindowManager's ComponentCallbacks() for internal UI changes (similar to an Activity) + * which comes via a different channel */ - private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE | CHANGE_DENSITY; - private final DisplayController.DisplayInfoChangeListener mDispInfoChangeListener; + private final OnIDPChangeListener mIdpChangeListener = c -> recreateTaskbar(); + private final SettingsCache.OnChangeListener mOnSettingsChangeListener = c -> recreateTaskbar(); private boolean mUserUnlocked = false; @@ -167,15 +170,11 @@ public class TaskbarManager { @SuppressLint("WrongConstant") public TaskbarManager(TouchInteractionService service) { - mDisplayController = DisplayController.INSTANCE.get(service); Display display = service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY); mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null); mNavButtonController = new TaskbarNavButtonController(service, SystemUiProxy.INSTANCE.get(mContext), new Handler()); - mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar(); - mNavBarKidsModeListener = isNavBarKidsMode -> recreateTaskbar(); - // TODO(b/227669780): Consolidate this w/ DisplayController callbacks mComponentCallbacks = new ComponentCallbacks() { private Configuration mOldConfig = mContext.getResources().getConfiguration(); @@ -186,80 +185,42 @@ public class TaskbarManager { DeviceProfile dp = mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null; - int configDiff = mOldConfig.diff(newConfig); - int configDiffForRecreate = configDiff; - int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS - | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE - | ActivityInfo.CONFIG_SCREEN_SIZE; - if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0 - && mTaskbarActivityContext != null && dp != null - && !isPhoneMode(dp)) { - // Additional check since this callback gets fired multiple times w/o - // screen size changing, or when simply rotating the device. - // In the case of phone device rotation, we do want to call recreateTaskbar() - DeviceProfile oldDp = mTaskbarActivityContext.getDeviceProfile(); - boolean isOrientationChange = - (configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0; + int configDiff = mOldConfig.diff(newConfig) & ~SKIP_RECREATE_CONFIG_CHANGES; - int newOrientation = newConfig.windowConfiguration.getRotation(); - int oldOrientation = mOldConfig.windowConfiguration.getRotation(); - int oldWidth = isOrientationChange ? oldDp.heightPx : oldDp.widthPx; - int oldHeight = isOrientationChange ? oldDp.widthPx : oldDp.heightPx; - - if ((dp.widthPx == oldWidth && dp.heightPx == oldHeight) - || (newOrientation == oldOrientation)) { - configDiffForRecreate &= ~ActivityInfo.CONFIG_SCREEN_SIZE; - } - } if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0) { // Only recreate for theme changes, not other UI mode changes such as docking. int oldUiNightMode = (mOldConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK); int newUiNightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK); if (oldUiNightMode == newUiNightMode) { - configDiffForRecreate &= ~ActivityInfo.CONFIG_UI_MODE; + configDiff &= ~ActivityInfo.CONFIG_UI_MODE; } } debugWhyTaskbarNotDestroyed("ComponentCallbacks#onConfigurationChanged() " - + "configDiffForRecreate=" - + Configuration.configurationDiffToString(configDiffForRecreate)); - if ((configDiffForRecreate & configsRequiringRecreate) != 0) { + + "configDiff=" + Configuration.configurationDiffToString(configDiff)); + if (configDiff != 0 || mTaskbarActivityContext == null) { recreateTaskbar(); } else { // Config change might be handled without re-creating the taskbar - if (mTaskbarActivityContext != null) { - if (dp != null && !isTaskbarPresent(dp)) { - destroyExistingTaskbar(); - } else { - if (dp != null && isTaskbarPresent(dp)) { - mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode); - } - mTaskbarActivityContext.onConfigurationChanged(configDiff); + if (dp != null && !isTaskbarPresent(dp)) { + destroyExistingTaskbar(); + } else { + if (dp != null && isTaskbarPresent(dp)) { + mTaskbarActivityContext.updateDeviceProfile(dp); } + mTaskbarActivityContext.onConfigurationChanged(configDiff); } } - mOldConfig = newConfig; + mOldConfig = new Configuration(newConfig); } @Override public void onLowMemory() { } }; - mShutdownReceiver = new SimpleBroadcastReceiver(i -> - destroyExistingTaskbar()); - mDispInfoChangeListener = (context, info, flags) -> { - if ((flags & CHANGE_FLAGS) != 0) { - mNavMode = info.navigationMode; - recreateTaskbar(); - } - debugWhyTaskbarNotDestroyed("DisplayInfoChangeListener#" - + mDisplayController.getChangeFlagsString(flags)); - }; - mNavMode = mDisplayController.getInfo().navigationMode; - mDisplayController.addChangeListener(mDispInfoChangeListener); - SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI, - mUserSetupCompleteListener); - SettingsCache.INSTANCE.get(mContext).register(NAV_BAR_KIDS_MODE, - mNavBarKidsModeListener); + SettingsCache.INSTANCE.get(mContext) + .register(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener); + SettingsCache.INSTANCE.get(mContext) + .register(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener); mContext.registerComponentCallbacks(mComponentCallbacks); mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN); UI_HELPER_EXECUTOR.execute(() -> { @@ -315,6 +276,7 @@ public class TaskbarManager { */ public void onUserUnlocked() { mUserUnlocked = true; + LauncherAppState.getIDP(mContext).addOnChangeListener(mIdpChangeListener); recreateTaskbar(); } @@ -398,7 +360,7 @@ public class TaskbarManager { mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp, mNavButtonController, mUnfoldProgressProvider); } else { - mTaskbarActivityContext.updateDeviceProfile(dp, mNavMode); + mTaskbarActivityContext.updateDeviceProfile(dp); } mTaskbarActivityContext.init(mSharedState); @@ -501,11 +463,13 @@ public class TaskbarManager { UI_HELPER_EXECUTOR.execute( () -> mTaskbarBroadcastReceiver.unregisterReceiverSafely(mContext)); destroyExistingTaskbar(); - mDisplayController.removeChangeListener(mDispInfoChangeListener); - SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI, - mUserSetupCompleteListener); - SettingsCache.INSTANCE.get(mContext).unregister(NAV_BAR_KIDS_MODE, - mNavBarKidsModeListener); + if (mUserUnlocked) { + LauncherAppState.getIDP(mContext).removeOnChangeListener(mIdpChangeListener); + } + SettingsCache.INSTANCE.get(mContext) + .unregister(USER_SETUP_COMPLETE_URI, mOnSettingsChangeListener); + SettingsCache.INSTANCE.get(mContext) + .unregister(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener); mContext.unregisterComponentCallbacks(mComponentCallbacks); mContext.unregisterReceiver(mShutdownReceiver); }