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
This commit is contained in:
Sunny Goyal
2023-06-14 16:01:02 -07:00
parent 95a8ff28ed
commit c87f7c74ef
2 changed files with 88 additions and 129 deletions

View File

@@ -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);
}