Loading quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +63 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON; import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NO_OFFSET; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; Loading Loading @@ -70,6 +72,7 @@ import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.NavigationMode; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ObjectWrapper; import com.android.launcher3.util.PendingSplitSelectInfo; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.util.UiThreadHelper; Loading @@ -91,10 +94,10 @@ import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.unfold.UnfoldTransitionFactory; import com.android.systemui.unfold.UnfoldTransitionProgressProvider; import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig; import com.android.systemui.unfold.config.UnfoldTransitionConfig; import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider; import com.android.systemui.unfold.system.DeviceStateManagerFoldProvider; import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -130,9 +133,19 @@ public abstract class BaseQuickstepLauncher extends Launcher { private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider; private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController; /** * If Launcher restarted while in the middle of an Overview split select, it needs this data to * recover. In all other cases this will remain null. */ private PendingSplitSelectInfo mPendingSplitSelectInfo = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { mPendingSplitSelectInfo = ObjectWrapper.unwrap( savedInstanceState.getIBinder(PENDING_SPLIT_SELECT_INFO)); } addMultiWindowModeChangedListener(mDepthController); initUnfoldTransitionProgressProvider(); } Loading Loading @@ -643,4 +656,53 @@ public abstract class BaseQuickstepLauncher extends Launcher { mDepthController.dump(prefix, writer); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // If Launcher shuts downs during split select, we save some extra data in the recovery // bundle to allow graceful recovery. The normal LauncherState restore mechanism doesn't // work in this case because restoring straight to OverviewSplitSelect without staging data, // or before the tasks themselves have loaded into Overview, causes a crash. So we tell // Launcher to first restore into Overview state, wait for the relevant tasks and icons to // load in, and then proceed to OverviewSplitSelect. if (isInState(OVERVIEW_SPLIT_SELECT)) { SplitSelectStateController splitSelectStateController = ((RecentsView) getOverviewPanel()).getSplitPlaceholder(); // Launcher will restart in Overview and then transition to OverviewSplitSelect. outState.putIBinder(PENDING_SPLIT_SELECT_INFO, ObjectWrapper.wrap( new PendingSplitSelectInfo( splitSelectStateController.getInitialTaskId(), splitSelectStateController.getActiveSplitStagePosition() ) )); outState.putInt(RUNTIME_STATE, OVERVIEW.ordinal); } } /** * When Launcher restarts, it sometimes needs to recover to a split selection state. * This function checks if such a recovery is needed. * @return a boolean representing whether the launcher is waiting to recover to * OverviewSplitSelect state. */ public boolean hasPendingSplitSelectInfo() { return mPendingSplitSelectInfo != null; } /** * See {@link #hasPendingSplitSelectInfo()} */ public @Nullable PendingSplitSelectInfo getPendingSplitSelectInfo() { return mPendingSplitSelectInfo; } /** * When the launcher has successfully recovered to OverviewSplitSelect state, this function * deletes the recovery data, returning it to a null state. */ public void finishSplitSelectRecovery() { mPendingSplitSelectInfo = null; } } quickstep/src/com/android/quickstep/RecentsModel.java +11 −17 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.launcher3.icons.IconProvider.IconChangeListener; import com.android.launcher3.util.Executors.SimpleThreadFactory; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.quickstep.util.GroupTask; import com.android.quickstep.util.TaskVisualsChangeListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -54,7 +55,8 @@ import java.util.function.Consumer; * Singleton class to load and manage recents model. */ @TargetApi(Build.VERSION_CODES.O) public class RecentsModel implements IconChangeListener, TaskStackChangeListener { public class RecentsModel implements IconChangeListener, TaskStackChangeListener, TaskVisualsChangeListener { // We do not need any synchronization for this variable as its only written on UI thread. public static final MainThreadInitializedObject<RecentsModel> INSTANCE = Loading @@ -77,6 +79,7 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener IconProvider iconProvider = new IconProvider(context); mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider); mIconCache.registerTaskVisualsChangeListener(this); mThumbnailCache = new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR); TaskStackChangeListeners.getInstance().registerTaskStackListener(this); Loading Loading @@ -203,6 +206,13 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener } } @Override public void onTaskIconChanged(int taskId) { for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) { listener.onTaskIconChanged(taskId); } } @Override public void onSystemIconStateChanged(String iconState) { mIconCache.clearCache(); Loading @@ -226,20 +236,4 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener writer.println(prefix + "RecentsModel:"); mTaskList.dump(" ", writer); } /** * Listener for receiving various task properties changes */ public interface TaskVisualsChangeListener { /** * Called whn the task thumbnail changes */ Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData); /** * Called when the icon for a task changes */ void onTaskIconChanged(String pkg, UserHandle user); } } quickstep/src/com/android/quickstep/TaskIconCache.java +20 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.quickstep; import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED; import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; import android.content.Context; Loading Loading @@ -46,6 +47,7 @@ import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.TaskKeyLruCache; import com.android.quickstep.util.TaskVisualsChangeListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.system.PackageManagerWrapper; Loading @@ -70,6 +72,9 @@ public class TaskIconCache implements DisplayInfoChangeListener { private BaseIconFactory mIconFactory; @Nullable public TaskVisualsChangeListener mTaskVisualsChangeListener = null; public TaskIconCache(Context context, Executor bgExecutor, IconProvider iconProvider) { mContext = context; mBgExecutor = bgExecutor; Loading Loading @@ -116,6 +121,7 @@ public class TaskIconCache implements DisplayInfoChangeListener { task.icon = result.icon; task.titleDescription = result.contentDescription; callback.accept(task); dispatchIconUpdate(task.key.id); } }; mBgExecutor.execute(request); Loading Loading @@ -272,4 +278,18 @@ public class TaskIconCache implements DisplayInfoChangeListener { public Drawable icon; public String contentDescription = ""; } void registerTaskVisualsChangeListener(TaskVisualsChangeListener newListener) { mTaskVisualsChangeListener = newListener; } void removeTaskVisualsChangeListener() { mTaskVisualsChangeListener = null; } void dispatchIconUpdate(int taskId) { if (mTaskVisualsChangeListener != null) { mTaskVisualsChangeListener.onTaskIconChanged(taskId); } } } quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +4 −0 Original line number Diff line number Diff line Loading @@ -330,4 +330,8 @@ public class SplitSelectStateController { private boolean isInitialTaskIntentSet() { return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null); } public int getInitialTaskId() { return mInitialTaskId; } } quickstep/src/com/android/quickstep/util/TaskVisualsChangeListener.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.quickstep.util; import android.os.UserHandle; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; /** * Listener for receiving various task properties changes */ public interface TaskVisualsChangeListener { /** * Called when the task thumbnail changes */ default Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) { return null; } /** * Called when the icon for a task changes */ default void onTaskIconChanged(String pkg, UserHandle user) {} /** * Called when the icon for a task changes */ default void onTaskIconChanged(int taskId) {} } Loading
quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +63 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON; import static com.android.launcher3.LauncherState.FLAG_HIDE_BACK_BUTTON; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NO_OFFSET; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; Loading Loading @@ -70,6 +72,7 @@ import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.NavigationMode; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ObjectWrapper; import com.android.launcher3.util.PendingSplitSelectInfo; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption; import com.android.launcher3.util.UiThreadHelper; Loading @@ -91,10 +94,10 @@ import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.unfold.UnfoldTransitionFactory; import com.android.systemui.unfold.UnfoldTransitionProgressProvider; import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig; import com.android.systemui.unfold.config.UnfoldTransitionConfig; import com.android.systemui.unfold.system.ActivityManagerActivityTypeProvider; import com.android.systemui.unfold.system.DeviceStateManagerFoldProvider; import com.android.systemui.unfold.config.ResourceUnfoldTransitionConfig; import java.io.FileDescriptor; import java.io.PrintWriter; Loading Loading @@ -130,9 +133,19 @@ public abstract class BaseQuickstepLauncher extends Launcher { private @Nullable UnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider; private @Nullable LauncherUnfoldAnimationController mLauncherUnfoldAnimationController; /** * If Launcher restarted while in the middle of an Overview split select, it needs this data to * recover. In all other cases this will remain null. */ private PendingSplitSelectInfo mPendingSplitSelectInfo = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null) { mPendingSplitSelectInfo = ObjectWrapper.unwrap( savedInstanceState.getIBinder(PENDING_SPLIT_SELECT_INFO)); } addMultiWindowModeChangedListener(mDepthController); initUnfoldTransitionProgressProvider(); } Loading Loading @@ -643,4 +656,53 @@ public abstract class BaseQuickstepLauncher extends Launcher { mDepthController.dump(prefix, writer); } } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // If Launcher shuts downs during split select, we save some extra data in the recovery // bundle to allow graceful recovery. The normal LauncherState restore mechanism doesn't // work in this case because restoring straight to OverviewSplitSelect without staging data, // or before the tasks themselves have loaded into Overview, causes a crash. So we tell // Launcher to first restore into Overview state, wait for the relevant tasks and icons to // load in, and then proceed to OverviewSplitSelect. if (isInState(OVERVIEW_SPLIT_SELECT)) { SplitSelectStateController splitSelectStateController = ((RecentsView) getOverviewPanel()).getSplitPlaceholder(); // Launcher will restart in Overview and then transition to OverviewSplitSelect. outState.putIBinder(PENDING_SPLIT_SELECT_INFO, ObjectWrapper.wrap( new PendingSplitSelectInfo( splitSelectStateController.getInitialTaskId(), splitSelectStateController.getActiveSplitStagePosition() ) )); outState.putInt(RUNTIME_STATE, OVERVIEW.ordinal); } } /** * When Launcher restarts, it sometimes needs to recover to a split selection state. * This function checks if such a recovery is needed. * @return a boolean representing whether the launcher is waiting to recover to * OverviewSplitSelect state. */ public boolean hasPendingSplitSelectInfo() { return mPendingSplitSelectInfo != null; } /** * See {@link #hasPendingSplitSelectInfo()} */ public @Nullable PendingSplitSelectInfo getPendingSplitSelectInfo() { return mPendingSplitSelectInfo; } /** * When the launcher has successfully recovered to OverviewSplitSelect state, this function * deletes the recovery data, returning it to a null state. */ public void finishSplitSelectRecovery() { mPendingSplitSelectInfo = null; } }
quickstep/src/com/android/quickstep/RecentsModel.java +11 −17 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.launcher3.icons.IconProvider.IconChangeListener; import com.android.launcher3.util.Executors.SimpleThreadFactory; import com.android.launcher3.util.MainThreadInitializedObject; import com.android.quickstep.util.GroupTask; import com.android.quickstep.util.TaskVisualsChangeListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -54,7 +55,8 @@ import java.util.function.Consumer; * Singleton class to load and manage recents model. */ @TargetApi(Build.VERSION_CODES.O) public class RecentsModel implements IconChangeListener, TaskStackChangeListener { public class RecentsModel implements IconChangeListener, TaskStackChangeListener, TaskVisualsChangeListener { // We do not need any synchronization for this variable as its only written on UI thread. public static final MainThreadInitializedObject<RecentsModel> INSTANCE = Loading @@ -77,6 +79,7 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener IconProvider iconProvider = new IconProvider(context); mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider); mIconCache.registerTaskVisualsChangeListener(this); mThumbnailCache = new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR); TaskStackChangeListeners.getInstance().registerTaskStackListener(this); Loading Loading @@ -203,6 +206,13 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener } } @Override public void onTaskIconChanged(int taskId) { for (TaskVisualsChangeListener listener : mThumbnailChangeListeners) { listener.onTaskIconChanged(taskId); } } @Override public void onSystemIconStateChanged(String iconState) { mIconCache.clearCache(); Loading @@ -226,20 +236,4 @@ public class RecentsModel implements IconChangeListener, TaskStackChangeListener writer.println(prefix + "RecentsModel:"); mTaskList.dump(" ", writer); } /** * Listener for receiving various task properties changes */ public interface TaskVisualsChangeListener { /** * Called whn the task thumbnail changes */ Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData); /** * Called when the icon for a task changes */ void onTaskIconChanged(String pkg, UserHandle user); } }
quickstep/src/com/android/quickstep/TaskIconCache.java +20 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.quickstep; import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED; import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; import android.content.Context; Loading Loading @@ -46,6 +47,7 @@ import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.Preconditions; import com.android.quickstep.util.CancellableTask; import com.android.quickstep.util.TaskKeyLruCache; import com.android.quickstep.util.TaskVisualsChangeListener; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.system.PackageManagerWrapper; Loading @@ -70,6 +72,9 @@ public class TaskIconCache implements DisplayInfoChangeListener { private BaseIconFactory mIconFactory; @Nullable public TaskVisualsChangeListener mTaskVisualsChangeListener = null; public TaskIconCache(Context context, Executor bgExecutor, IconProvider iconProvider) { mContext = context; mBgExecutor = bgExecutor; Loading Loading @@ -116,6 +121,7 @@ public class TaskIconCache implements DisplayInfoChangeListener { task.icon = result.icon; task.titleDescription = result.contentDescription; callback.accept(task); dispatchIconUpdate(task.key.id); } }; mBgExecutor.execute(request); Loading Loading @@ -272,4 +278,18 @@ public class TaskIconCache implements DisplayInfoChangeListener { public Drawable icon; public String contentDescription = ""; } void registerTaskVisualsChangeListener(TaskVisualsChangeListener newListener) { mTaskVisualsChangeListener = newListener; } void removeTaskVisualsChangeListener() { mTaskVisualsChangeListener = null; } void dispatchIconUpdate(int taskId) { if (mTaskVisualsChangeListener != null) { mTaskVisualsChangeListener.onTaskIconChanged(taskId); } } }
quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +4 −0 Original line number Diff line number Diff line Loading @@ -330,4 +330,8 @@ public class SplitSelectStateController { private boolean isInitialTaskIntentSet() { return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null); } public int getInitialTaskId() { return mInitialTaskId; } }
quickstep/src/com/android/quickstep/util/TaskVisualsChangeListener.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.quickstep.util; import android.os.UserHandle; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; /** * Listener for receiving various task properties changes */ public interface TaskVisualsChangeListener { /** * Called when the task thumbnail changes */ default Task onTaskThumbnailChanged(int taskId, ThumbnailData thumbnailData) { return null; } /** * Called when the icon for a task changes */ default void onTaskIconChanged(String pkg, UserHandle user) {} /** * Called when the icon for a task changes */ default void onTaskIconChanged(int taskId) {} }