Merge "Add callback to notify frozen RecentTasks"
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index 750020e..0ba1989 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -197,4 +197,11 @@
      * Called when any additions or deletions to the recent tasks list have been made.
      */
     void onRecentTaskListUpdated();
+
+    /**
+     * Called when Recent Tasks list is frozen or unfrozen.
+     *
+     * @param frozen if true, Recents Tasks list is currently frozen, false otherwise
+     */
+    void onRecentTaskListFrozenChanged(boolean frozen);
 }
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 46045fa..f21aaf3 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -190,4 +190,8 @@
     @Override
     public void onRecentTaskListUpdated() throws RemoteException {
     }
+
+    @Override
+    public void onRecentTaskListFrozenChanged(boolean frozen) {
+    }
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 5ddf89c..6186589 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -17,6 +17,7 @@
 package com.android.systemui.shared.system;
 
 import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ITaskStackListener;
 import android.content.ComponentName;
 import android.os.IBinder;
 import android.os.UserHandle;
@@ -106,6 +107,9 @@
      */
     public void onRecentTaskListUpdated() { }
 
+    /** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */
+    public void onRecentTaskListFrozenChanged(boolean frozen) { }
+
     /**
      * Checks that the current user matches the process. Since
      * {@link android.app.ITaskStackListener} is not multi-user aware, handlers of
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 820057a..8d823ca 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -224,6 +224,12 @@
         mHandler.obtainMessage(H.ON_TASK_LIST_UPDATED).sendToTarget();
     }
 
+    @Override
+    public void onRecentTaskListFrozenChanged(boolean frozen) {
+        mHandler.obtainMessage(H.ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0, 0 /* unused */)
+                .sendToTarget();
+    }
+
     private final class H extends Handler {
         private static final int ON_TASK_STACK_CHANGED = 1;
         private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -247,6 +253,7 @@
         private static final int ON_TASK_DISPLAY_CHANGED = 20;
         private static final int ON_TASK_LIST_UPDATED = 21;
         private static final int ON_SINGLE_TASK_DISPLAY_EMPTY = 22;
+        private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 23;
 
 
         public H(Looper looper) {
@@ -408,6 +415,12 @@
                         }
                         break;
                     }
+                    case ON_TASK_LIST_FROZEN_UNFROZEN: {
+                        for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+                            mTaskStackListeners.get(i).onRecentTaskListFrozenChanged(msg.arg1 != 0);
+                        }
+                        break;
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index fb6b5da..1543f3f 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -272,9 +272,14 @@
      * app, or a timeout occurs.
      */
     void setFreezeTaskListReordering() {
+        // Only fire the callback once per quickswitch session, not on every individual switch
+        if (!mFreezeTaskListReordering) {
+            mTaskNotificationController.notifyTaskListFrozen(true);
+            mFreezeTaskListReordering = true;
+        }
+
         // Always update the reordering time when this is called to ensure that the timeout
         // is reset
-        mFreezeTaskListReordering = true;
         mService.mH.removeCallbacks(mResetFreezeTaskListOnTimeoutRunnable);
         mService.mH.postDelayed(mResetFreezeTaskListOnTimeoutRunnable, mFreezeTaskListTimeoutMs);
     }
@@ -302,6 +307,7 @@
         trimInactiveRecentTasks();
 
         mTaskNotificationController.notifyTaskStackChanged();
+        mTaskNotificationController.notifyTaskListFrozen(false);
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index 5e8831d..368d81f1 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -58,6 +58,7 @@
     private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 23;
     private static final int NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG = 24;
     private static final int NOTIFY_SINGLE_TASK_DISPLAY_EMPTY = 25;
+    private static final int NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG = 26;
 
     // Delay in notifying task stack change listeners (in millis)
     private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
@@ -174,6 +175,10 @@
         l.onRecentTaskListUpdated();
     };
 
+    private final TaskStackConsumer mNotifyTaskListFrozen = (l, m) -> {
+        l.onRecentTaskListFrozenChanged(m.arg1 != 0);
+    };
+
     @FunctionalInterface
     public interface TaskStackConsumer {
         void accept(ITaskStackListener t, Message m) throws RemoteException;
@@ -265,6 +270,9 @@
                 case NOTIFY_TASK_LIST_UPDATED_LISTENERS_MSG:
                     forAllRemoteListeners(mNotifyTaskListUpdated, msg);
                     break;
+                case NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG:
+                    forAllRemoteListeners(mNotifyTaskListFrozen, msg);
+                    break;
             }
         }
     }
@@ -549,4 +557,12 @@
         forAllLocalListeners(mNotifyTaskListUpdated, msg);
         msg.sendToTarget();
     }
+
+    /** @see ITaskStackListener#onRecentTaskListFrozenChanged(boolean) */
+    void notifyTaskListFrozen(boolean frozen) {
+        final Message msg = mHandler.obtainMessage(NOTIFY_TASK_LIST_FROZEN_UNFROZEN_MSG,
+                frozen ? 1 : 0, 0 /* unused */);
+        forAllLocalListeners(mNotifyTaskListFrozen, msg);
+        msg.sendToTarget();
+    }
 }