2021-05-20 20:18:47 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2021 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.launcher3.taskbar;
|
|
|
|
|
|
|
|
|
|
import static android.view.Display.DEFAULT_DISPLAY;
|
2021-10-21 15:31:51 +01:00
|
|
|
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
|
2021-11-03 11:17:44 -07:00
|
|
|
|
|
|
|
|
import static com.android.launcher3.testing.TestProtocol.TASKBAR_WINDOW_CRASH;
|
2021-05-20 20:18:47 +00:00
|
|
|
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
|
|
|
|
|
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
|
|
|
|
|
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
|
|
|
|
|
|
2021-09-07 12:15:25 -07:00
|
|
|
import android.content.ComponentCallbacks;
|
2021-05-20 20:18:47 +00:00
|
|
|
import android.content.Context;
|
2021-09-10 14:13:35 -07:00
|
|
|
import android.content.Intent;
|
2021-09-07 12:15:25 -07:00
|
|
|
import android.content.pm.ActivityInfo;
|
|
|
|
|
import android.content.res.Configuration;
|
2021-05-20 20:18:47 +00:00
|
|
|
import android.hardware.display.DisplayManager;
|
2021-08-26 14:35:52 -07:00
|
|
|
import android.net.Uri;
|
|
|
|
|
import android.provider.Settings;
|
2021-11-03 11:17:44 -07:00
|
|
|
import android.util.Log;
|
2021-05-20 20:18:47 +00:00
|
|
|
import android.view.Display;
|
|
|
|
|
|
2021-06-18 12:41:22 -07:00
|
|
|
import androidx.annotation.NonNull;
|
2021-07-16 12:15:35 -10:00
|
|
|
import androidx.annotation.Nullable;
|
2021-05-20 20:18:47 +00:00
|
|
|
|
|
|
|
|
import com.android.launcher3.BaseQuickstepLauncher;
|
|
|
|
|
import com.android.launcher3.DeviceProfile;
|
|
|
|
|
import com.android.launcher3.LauncherAppState;
|
|
|
|
|
import com.android.launcher3.config.FeatureFlags;
|
2021-10-18 16:02:21 -07:00
|
|
|
import com.android.launcher3.statemanager.StatefulActivity;
|
2021-05-20 20:18:47 +00:00
|
|
|
import com.android.launcher3.util.DisplayController;
|
|
|
|
|
import com.android.launcher3.util.DisplayController.Info;
|
2021-08-26 14:35:52 -07:00
|
|
|
import com.android.launcher3.util.SettingsCache;
|
2021-09-10 14:13:35 -07:00
|
|
|
import com.android.launcher3.util.SimpleBroadcastReceiver;
|
2021-10-18 16:02:21 -07:00
|
|
|
import com.android.quickstep.RecentsActivity;
|
2021-05-20 20:18:47 +00:00
|
|
|
import com.android.quickstep.SysUINavigationMode;
|
|
|
|
|
import com.android.quickstep.SysUINavigationMode.Mode;
|
2021-06-30 10:24:11 +00:00
|
|
|
import com.android.quickstep.SystemUiProxy;
|
2021-05-20 20:18:47 +00:00
|
|
|
import com.android.quickstep.TouchInteractionService;
|
2021-10-18 16:02:21 -07:00
|
|
|
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
|
2021-10-13 17:04:16 +01:00
|
|
|
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
|
2021-05-20 20:18:47 +00:00
|
|
|
|
|
|
|
|
/**
|
2021-05-25 19:26:48 -07:00
|
|
|
* Class to manage taskbar lifecycle
|
2021-05-20 20:18:47 +00:00
|
|
|
*/
|
|
|
|
|
public class TaskbarManager implements DisplayController.DisplayInfoChangeListener,
|
2021-05-25 14:35:01 -07:00
|
|
|
SysUINavigationMode.NavigationModeChangeListener {
|
2021-05-20 20:18:47 +00:00
|
|
|
|
2021-08-26 14:35:52 -07:00
|
|
|
private static final Uri USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(
|
|
|
|
|
Settings.Secure.USER_SETUP_COMPLETE);
|
|
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
private final Context mContext;
|
|
|
|
|
private final DisplayController mDisplayController;
|
|
|
|
|
private final SysUINavigationMode mSysUINavigationMode;
|
|
|
|
|
private final TaskbarNavButtonController mNavButtonController;
|
2021-08-26 14:35:52 -07:00
|
|
|
private final SettingsCache.OnChangeListener mUserSetupCompleteListener;
|
2021-09-07 12:15:25 -07:00
|
|
|
private final ComponentCallbacks mComponentCallbacks;
|
2021-09-10 14:13:35 -07:00
|
|
|
private final SimpleBroadcastReceiver mShutdownReceiver;
|
2021-05-20 20:18:47 +00:00
|
|
|
|
2021-08-27 14:11:53 +01:00
|
|
|
// The source for this provider is set when Launcher is available
|
|
|
|
|
private final ScopedUnfoldTransitionProgressProvider mUnfoldProgressProvider =
|
|
|
|
|
new ScopedUnfoldTransitionProgressProvider();
|
|
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
private TaskbarActivityContext mTaskbarActivityContext;
|
2021-10-18 16:02:21 -07:00
|
|
|
private StatefulActivity mActivity;
|
2021-06-07 16:42:43 -07:00
|
|
|
/**
|
|
|
|
|
* Cache a copy here so we can initialize state whenever taskbar is recreated, since
|
|
|
|
|
* this class does not get re-initialized w/ new taskbars.
|
|
|
|
|
*/
|
2021-10-01 11:31:45 -07:00
|
|
|
private final TaskbarSharedState mSharedState = new TaskbarSharedState();
|
2021-05-20 20:18:47 +00:00
|
|
|
|
|
|
|
|
private static final int CHANGE_FLAGS =
|
|
|
|
|
CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY | CHANGE_SUPPORTED_BOUNDS;
|
|
|
|
|
|
2021-05-20 13:45:58 -07:00
|
|
|
private boolean mUserUnlocked = false;
|
|
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
public TaskbarManager(TouchInteractionService service) {
|
|
|
|
|
mDisplayController = DisplayController.INSTANCE.get(service);
|
|
|
|
|
mSysUINavigationMode = SysUINavigationMode.INSTANCE.get(service);
|
|
|
|
|
Display display =
|
|
|
|
|
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
|
2021-10-21 15:31:51 +01:00
|
|
|
mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
|
2021-05-20 20:18:47 +00:00
|
|
|
mNavButtonController = new TaskbarNavButtonController(service);
|
2021-08-26 14:35:52 -07:00
|
|
|
mUserSetupCompleteListener = isUserSetupComplete -> recreateTaskbar();
|
2021-09-07 12:15:25 -07:00
|
|
|
mComponentCallbacks = new ComponentCallbacks() {
|
|
|
|
|
private Configuration mOldConfig = mContext.getResources().getConfiguration();
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
2021-10-05 17:44:06 -07:00
|
|
|
int configDiff = mOldConfig.diff(newConfig);
|
|
|
|
|
int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
|
2021-10-28 16:39:32 -07:00
|
|
|
| ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE;
|
2021-10-05 17:44:06 -07:00
|
|
|
if ((configDiff & configsRequiringRecreate) != 0) {
|
2021-09-07 12:15:25 -07:00
|
|
|
// Color has changed, recreate taskbar to reload background color & icons.
|
|
|
|
|
recreateTaskbar();
|
|
|
|
|
}
|
|
|
|
|
mOldConfig = newConfig;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onLowMemory() { }
|
|
|
|
|
};
|
2021-09-10 14:13:35 -07:00
|
|
|
mShutdownReceiver = new SimpleBroadcastReceiver(i -> destroyExistingTaskbar());
|
2021-05-20 20:18:47 +00:00
|
|
|
|
|
|
|
|
mDisplayController.addChangeListener(this);
|
|
|
|
|
mSysUINavigationMode.addModeChangeListener(this);
|
2021-08-26 14:35:52 -07:00
|
|
|
SettingsCache.INSTANCE.get(mContext).register(USER_SETUP_COMPLETE_URI,
|
|
|
|
|
mUserSetupCompleteListener);
|
2021-09-07 12:15:25 -07:00
|
|
|
mContext.registerComponentCallbacks(mComponentCallbacks);
|
2021-09-10 14:13:35 -07:00
|
|
|
mShutdownReceiver.register(mContext, Intent.ACTION_SHUTDOWN);
|
2021-08-26 14:35:52 -07:00
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
recreateTaskbar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onNavigationModeChanged(Mode newMode) {
|
|
|
|
|
recreateTaskbar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void onDisplayInfoChanged(Context context, Info info, int flags) {
|
|
|
|
|
if ((flags & CHANGE_FLAGS) != 0) {
|
|
|
|
|
recreateTaskbar();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void destroyExistingTaskbar() {
|
|
|
|
|
if (mTaskbarActivityContext != null) {
|
|
|
|
|
mTaskbarActivityContext.onDestroy();
|
|
|
|
|
mTaskbarActivityContext = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-20 13:45:58 -07:00
|
|
|
/**
|
|
|
|
|
* Called when the user is unlocked
|
|
|
|
|
*/
|
|
|
|
|
public void onUserUnlocked() {
|
|
|
|
|
mUserUnlocked = true;
|
|
|
|
|
recreateTaskbar();
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
/**
|
2021-10-18 16:02:21 -07:00
|
|
|
* Sets a {@link StatefulActivity} to act as taskbar callback
|
2021-05-20 20:18:47 +00:00
|
|
|
*/
|
2021-10-18 16:02:21 -07:00
|
|
|
public void setActivity(@NonNull StatefulActivity activity) {
|
|
|
|
|
mActivity = activity;
|
|
|
|
|
mUnfoldProgressProvider.setSourceProvider(getUnfoldTransitionProgressProviderForActivity(
|
|
|
|
|
activity));
|
2021-08-27 14:11:53 +01:00
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
if (mTaskbarActivityContext != null) {
|
2021-06-18 12:41:22 -07:00
|
|
|
mTaskbarActivityContext.setUIController(
|
2021-10-18 16:02:21 -07:00
|
|
|
createTaskbarUIControllerForActivity(mActivity));
|
2021-06-18 12:41:22 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2021-10-18 16:02:21 -07:00
|
|
|
* Returns an {@link UnfoldTransitionProgressProvider} to use while the given StatefulActivity
|
|
|
|
|
* is active.
|
2021-06-18 12:41:22 -07:00
|
|
|
*/
|
2021-10-18 16:02:21 -07:00
|
|
|
private UnfoldTransitionProgressProvider getUnfoldTransitionProgressProviderForActivity(
|
|
|
|
|
StatefulActivity activity) {
|
|
|
|
|
if (activity instanceof BaseQuickstepLauncher) {
|
|
|
|
|
return ((BaseQuickstepLauncher) activity).getUnfoldTransitionProgressProvider();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Creates a {@link TaskbarUIController} to use while the given StatefulActivity is active.
|
|
|
|
|
*/
|
|
|
|
|
private TaskbarUIController createTaskbarUIControllerForActivity(StatefulActivity activity) {
|
|
|
|
|
if (activity instanceof BaseQuickstepLauncher) {
|
|
|
|
|
return new LauncherTaskbarUIController((BaseQuickstepLauncher) activity);
|
|
|
|
|
}
|
|
|
|
|
if (activity instanceof RecentsActivity) {
|
|
|
|
|
return new FallbackTaskbarUIController((RecentsActivity) activity);
|
|
|
|
|
}
|
|
|
|
|
return TaskbarUIController.DEFAULT;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Clears a previously set {@link StatefulActivity}
|
|
|
|
|
*/
|
|
|
|
|
public void clearActivity(@NonNull StatefulActivity activity) {
|
|
|
|
|
if (mActivity == activity) {
|
|
|
|
|
mActivity = null;
|
2021-06-18 12:41:22 -07:00
|
|
|
if (mTaskbarActivityContext != null) {
|
|
|
|
|
mTaskbarActivityContext.setUIController(TaskbarUIController.DEFAULT);
|
|
|
|
|
}
|
2021-08-27 14:11:53 +01:00
|
|
|
mUnfoldProgressProvider.setSourceProvider(null);
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void recreateTaskbar() {
|
2021-11-05 09:40:03 -07:00
|
|
|
Log.d(TASKBAR_WINDOW_CRASH, "Recreating taskbar: mTaskbarActivityContext="
|
|
|
|
|
+ mTaskbarActivityContext);
|
2021-05-20 20:18:47 +00:00
|
|
|
destroyExistingTaskbar();
|
2021-06-30 10:24:11 +00:00
|
|
|
|
|
|
|
|
DeviceProfile dp =
|
|
|
|
|
mUserUnlocked ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext) : null;
|
|
|
|
|
|
|
|
|
|
boolean isTaskBarEnabled =
|
|
|
|
|
FeatureFlags.ENABLE_TASKBAR.get() && dp != null && dp.isTaskbarPresent;
|
|
|
|
|
|
|
|
|
|
if (!isTaskBarEnabled) {
|
|
|
|
|
SystemUiProxy.INSTANCE.get(mContext)
|
|
|
|
|
.notifyTaskbarStatus(/* visible */ false, /* stashed */ false);
|
2021-05-20 20:18:47 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2021-06-30 10:24:11 +00:00
|
|
|
|
2021-08-27 14:11:53 +01:00
|
|
|
mTaskbarActivityContext = new TaskbarActivityContext(mContext, dp.copy(mContext),
|
|
|
|
|
mNavButtonController, mUnfoldProgressProvider);
|
2021-10-18 16:02:21 -07:00
|
|
|
|
2021-10-01 11:31:45 -07:00
|
|
|
mTaskbarActivityContext.init(mSharedState);
|
2021-10-18 16:02:21 -07:00
|
|
|
if (mActivity != null) {
|
2021-05-20 20:18:47 +00:00
|
|
|
mTaskbarActivityContext.setUIController(
|
2021-10-18 16:02:21 -07:00
|
|
|
createTaskbarUIControllerForActivity(mActivity));
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
2021-11-05 09:40:03 -07:00
|
|
|
Log.d(TASKBAR_WINDOW_CRASH, "Finished recreating taskbar");
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onSystemUiFlagsChanged(int systemUiStateFlags) {
|
2021-10-01 11:31:45 -07:00
|
|
|
mSharedState.sysuiStateFlags = systemUiStateFlags;
|
|
|
|
|
if (mTaskbarActivityContext != null) {
|
2021-10-28 16:39:32 -07:00
|
|
|
mTaskbarActivityContext.updateSysuiStateFlags(systemUiStateFlags, false /* fromInit */);
|
2021-10-01 11:31:45 -07:00
|
|
|
}
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
|
|
|
|
|
2021-10-01 11:31:45 -07:00
|
|
|
/**
|
|
|
|
|
* Sets the flag indicating setup UI is visible
|
|
|
|
|
*/
|
|
|
|
|
public void setSetupUIVisible(boolean isVisible) {
|
|
|
|
|
mSharedState.setupUIVisible = isVisible;
|
2021-05-25 14:35:01 -07:00
|
|
|
if (mTaskbarActivityContext != null) {
|
2021-10-01 11:31:45 -07:00
|
|
|
mTaskbarActivityContext.setSetupUIVisible(isVisible);
|
2021-05-25 19:26:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onRotationProposal(int rotation, boolean isValid) {
|
2021-05-25 14:35:01 -07:00
|
|
|
if (mTaskbarActivityContext != null) {
|
|
|
|
|
mTaskbarActivityContext.onRotationProposal(rotation, isValid);
|
2021-05-25 19:26:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-04 15:35:46 -07:00
|
|
|
public void disableNavBarElements(int displayId, int state1, int state2, boolean animate) {
|
2021-05-25 14:35:01 -07:00
|
|
|
if (mTaskbarActivityContext != null) {
|
2021-06-04 15:35:46 -07:00
|
|
|
mTaskbarActivityContext.disableNavBarElements(displayId, state1, state2, animate);
|
2021-05-25 19:26:48 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void onSystemBarAttributesChanged(int displayId, int behavior) {
|
2021-05-25 14:35:01 -07:00
|
|
|
if (mTaskbarActivityContext != null) {
|
|
|
|
|
mTaskbarActivityContext.onSystemBarAttributesChanged(displayId, behavior);
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-04 16:53:59 -07:00
|
|
|
public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
|
|
|
|
|
if (mTaskbarActivityContext != null) {
|
|
|
|
|
mTaskbarActivityContext.onNavButtonsDarkIntensityChanged(darkIntensity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-20 20:18:47 +00:00
|
|
|
/**
|
|
|
|
|
* Called when the manager is no longer needed
|
|
|
|
|
*/
|
|
|
|
|
public void destroy() {
|
|
|
|
|
destroyExistingTaskbar();
|
|
|
|
|
mDisplayController.removeChangeListener(this);
|
|
|
|
|
mSysUINavigationMode.removeModeChangeListener(this);
|
2021-08-26 14:35:52 -07:00
|
|
|
SettingsCache.INSTANCE.get(mContext).unregister(USER_SETUP_COMPLETE_URI,
|
|
|
|
|
mUserSetupCompleteListener);
|
2021-09-07 12:15:25 -07:00
|
|
|
mContext.unregisterComponentCallbacks(mComponentCallbacks);
|
2021-09-10 14:13:35 -07:00
|
|
|
mContext.unregisterReceiver(mShutdownReceiver);
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|
2021-07-16 12:15:35 -10:00
|
|
|
|
|
|
|
|
public @Nullable TaskbarActivityContext getCurrentActivityContext() {
|
|
|
|
|
return mTaskbarActivityContext;
|
|
|
|
|
}
|
2021-05-20 20:18:47 +00:00
|
|
|
}
|