From 34e384d2e1a381e1b18e7da90227fb61b2e75172 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Tue, 23 Nov 2021 08:04:14 +0000 Subject: [PATCH] Fix issue with Shell listeners being unbound if SysUI is restarted - If SysUI is restarted (ie. during dev or a crash), the components registering the shell listeners may not be aware of this, and listener callbacks will not be re-registered. Currently all the listeners are managed correctly (bound & later unbound) so we can just keep the active listener references to re-register if this happens. Bug: 207142749 Test: Kill SysUI, start some apps and ensure Launcher still shows them in recents Change-Id: Iba3b11ee972caf8f0b482942d38c3a7359211180 --- .../android/quickstep/RecentTasksList.java | 21 ++++++ .../com/android/quickstep/RecentsModel.java | 6 ++ .../com/android/quickstep/SystemUiProxy.java | 72 ++++++++----------- .../quickstep/TouchInteractionService.java | 1 + 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java index c5f4a53877..097850fd6f 100644 --- a/quickstep/src/com/android/quickstep/RecentTasksList.java +++ b/quickstep/src/com/android/quickstep/RecentTasksList.java @@ -36,6 +36,7 @@ import com.android.wm.shell.recents.IRecentTasksListener; import com.android.wm.shell.util.GroupedRecentTaskInfo; import com.android.wm.shell.util.StagedSplitBounds; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.function.Consumer; @@ -219,6 +220,26 @@ public class RecentTasksList { return newTasks; } + public void dump(String prefix, PrintWriter writer) { + writer.println(prefix + "RecentTasksList:"); + writer.println(prefix + " mChangeId=" + mChangeId); + writer.println(prefix + " mResultsUi=[id=" + mResultsUi.mRequestId + ", tasks="); + for (GroupTask task : mResultsUi) { + writer.println(prefix + " t1=" + task.task1.key.id + + " t2=" + (task.hasMultipleTasks() ? task.task2.key.id : "-1")); + } + writer.println(prefix + " ]"); + int currentUserId = Process.myUserHandle().getIdentifier(); + ArrayList rawTasks = + mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId); + writer.println(prefix + " rawTasks=["); + for (GroupedRecentTaskInfo task : rawTasks) { + writer.println(prefix + " t1=" + task.mTaskInfo1.taskId + + " t2=" + (task.mTaskInfo2 != null ? task.mTaskInfo2.taskId : "-1")); + } + writer.println(prefix + " ]"); + } + private static class TaskLoadResult extends ArrayList { final int mRequestId; diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index e539a8c7c4..5d77a6e916 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -43,6 +43,7 @@ import com.android.systemui.shared.system.KeyguardManagerCompat; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executor; @@ -220,6 +221,11 @@ public class RecentsModel extends TaskStackChangeListener implements IconChangeL mThumbnailChangeListeners.remove(listener); } + public void dump(String prefix, PrintWriter writer) { + writer.println(prefix + "RecentsModel:"); + mTaskList.dump(" ", writer); + } + /** * Listener for receiving various task properties changes */ diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 68b7558cf2..c8abd14d22 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -83,14 +83,16 @@ public class SystemUiProxy implements ISystemUiProxy, MAIN_EXECUTOR.execute(() -> clearProxy()); }; - // Save the listeners passed into the proxy since when set/register these listeners, - // setProxy may not have been called, eg. OverviewProxyService is not connected yet. - private IPipAnimationListener mPendingPipAnimationListener; - private ISplitScreenListener mPendingSplitScreenListener; - private IStartingWindowListener mPendingStartingWindowListener; - private ISmartspaceCallback mPendingSmartspaceCallback; - private IRecentTasksListener mPendingRecentTasksListener; - private final ArrayList mPendingRemoteTransitions = new ArrayList<>(); + // Save the listeners passed into the proxy since OverviewProxyService may not have been bound + // yet, and we'll need to set/register these listeners with SysUI when they do. Note that it is + // up to the caller to clear the listeners to prevent leaks as these can be held indefinitely + // in case SysUI needs to rebind. + private IPipAnimationListener mPipAnimationListener; + private ISplitScreenListener mSplitScreenListener; + private IStartingWindowListener mStartingWindowListener; + private ISmartspaceCallback mSmartspaceCallback; + private IRecentTasksListener mRecentTasksListener; + private final ArrayList mRemoteTransitions = new ArrayList<>(); // Used to dedupe calls to SystemUI private int mLastShelfHeight; @@ -167,29 +169,23 @@ public class SystemUiProxy implements ISystemUiProxy, mRecentTasks = recentTasks; linkToDeath(); // re-attach the listeners once missing due to setProxy has not been initialized yet. - if (mPendingPipAnimationListener != null && mPip != null) { - setPinnedStackAnimationListener(mPendingPipAnimationListener); - mPendingPipAnimationListener = null; + if (mPipAnimationListener != null && mPip != null) { + setPinnedStackAnimationListener(mPipAnimationListener); } - if (mPendingSplitScreenListener != null && mSplitScreen != null) { - registerSplitScreenListener(mPendingSplitScreenListener); - mPendingSplitScreenListener = null; + if (mSplitScreenListener != null && mSplitScreen != null) { + registerSplitScreenListener(mSplitScreenListener); } - if (mPendingStartingWindowListener != null && mStartingWindow != null) { - setStartingWindowListener(mPendingStartingWindowListener); - mPendingStartingWindowListener = null; + if (mStartingWindowListener != null && mStartingWindow != null) { + setStartingWindowListener(mStartingWindowListener); } - if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) { - setSmartspaceCallback(mPendingSmartspaceCallback); - mPendingSmartspaceCallback = null; + if (mSmartspaceCallback != null && mSmartspaceTransitionController != null) { + setSmartspaceCallback(mSmartspaceCallback); } - for (int i = mPendingRemoteTransitions.size() - 1; i >= 0; --i) { - registerRemoteTransition(mPendingRemoteTransitions.get(i)); + for (int i = mRemoteTransitions.size() - 1; i >= 0; --i) { + registerRemoteTransition(mRemoteTransitions.get(i)); } - mPendingRemoteTransitions.clear(); - if (mPendingRecentTasksListener != null && mRecentTasks != null) { - registerRecentTasksListener(mPendingRecentTasksListener); - mPendingRecentTasksListener = null; + if (mRecentTasksListener != null && mRecentTasks != null) { + registerRecentTasksListener(mRecentTasksListener); } if (mPendingSetNavButtonAlpha != null) { @@ -513,9 +509,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call setPinnedStackAnimationListener", e); } - } else { - mPendingPipAnimationListener = listener; } + mPipAnimationListener = listener; } public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo, @@ -553,9 +548,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call registerSplitScreenListener"); } - } else { - mPendingSplitScreenListener = listener; } + mSplitScreenListener = listener; } public void unregisterSplitScreenListener(ISplitScreenListener listener) { @@ -566,7 +560,7 @@ public class SystemUiProxy implements ISystemUiProxy, Log.w(TAG, "Failed call unregisterSplitScreenListener"); } } - mPendingSplitScreenListener = null; + mSplitScreenListener = null; } /** Start multiple tasks in split-screen simultaneously. */ @@ -687,9 +681,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call registerRemoteTransition"); } - } else { - mPendingRemoteTransitions.add(remoteTransition); } + mRemoteTransitions.add(remoteTransition); } public void unregisterRemoteTransition(RemoteTransitionCompat remoteTransition) { @@ -700,7 +693,7 @@ public class SystemUiProxy implements ISystemUiProxy, Log.w(TAG, "Failed call registerRemoteTransition"); } } - mPendingRemoteTransitions.remove(remoteTransition); + mRemoteTransitions.remove(remoteTransition); } // @@ -717,9 +710,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call setStartingWindowListener", e); } - } else { - mPendingStartingWindowListener = listener; } + mStartingWindowListener = listener; } // @@ -733,9 +725,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call setStartingWindowListener", e); } - } else { - mPendingSmartspaceCallback = callback; } + mSmartspaceCallback = callback; } // @@ -749,9 +740,8 @@ public class SystemUiProxy implements ISystemUiProxy, } catch (RemoteException e) { Log.w(TAG, "Failed call registerRecentTasksListener", e); } - } else { - mPendingRecentTasksListener = listener; } + mRecentTasksListener = listener; } public void unregisterRecentTasksListener(IRecentTasksListener listener) { @@ -762,7 +752,7 @@ public class SystemUiProxy implements ISystemUiProxy, Log.w(TAG, "Failed call unregisterRecentTasksListener"); } } - mPendingRecentTasksListener = null; + mRecentTasksListener = null; } public ArrayList getRecentTasks(int numTasks, int userId) { diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index bda5a3044c..30dce61422 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -976,6 +976,7 @@ public class TouchInteractionService extends Service pw.println(" resumed=" + resumed); pw.println(" mConsumer=" + mConsumer.getName()); ActiveGestureLog.INSTANCE.dump("", pw); + RecentsModel.INSTANCE.get(this).dump("", pw); pw.println("ProtoTrace:"); pw.println(" file=" + ProtoTracer.INSTANCE.get(this).getTraceFile()); }