Throw exception from SystemUiProxy.getRecentTasks for invalid result

- The reason Recents is empty after a force-stop is when RecentsTasksList.getTasks is called first time after restart, the result is always invalid but we cached the invalid result with a chagneId(=1). The next time we call getTasks again, we think the cached result is valid, and returend an empty list.
- The fix is to mark such result as invalid to avoid caching the wrong result

Fix: 353926204
Test: RecentTasksListTest
Flag: EXEMPT bugfix
Change-Id: If15ab8fd7454db8a08c22b17eaac73f0c78aa75f
diff --git a/quickstep/src/com/android/quickstep/RecentTasksList.java b/quickstep/src/com/android/quickstep/RecentTasksList.java
index 3d4167a..4989831 100644
--- a/quickstep/src/com/android/quickstep/RecentTasksList.java
+++ b/quickstep/src/com/android/quickstep/RecentTasksList.java
@@ -300,8 +300,12 @@
     @VisibleForTesting
     TaskLoadResult loadTasksInBackground(int numTasks, int requestId, boolean loadKeysOnly) {
         int currentUserId = Process.myUserHandle().getIdentifier();
-        ArrayList<GroupedRecentTaskInfo> rawTasks =
-                mSysUiProxy.getRecentTasks(numTasks, currentUserId);
+        ArrayList<GroupedRecentTaskInfo> rawTasks;
+        try {
+            rawTasks = mSysUiProxy.getRecentTasks(numTasks, currentUserId);
+        } catch (SystemUiProxy.GetRecentTasksException e) {
+            return INVALID_RESULT;
+        }
         // The raw tasks are given in most-recent to least-recent order, we need to reverse it
         Collections.reverse(rawTasks);
 
@@ -416,8 +420,12 @@
         }
         writer.println(prefix + "  ]");
         int currentUserId = Process.myUserHandle().getIdentifier();
-        ArrayList<GroupedRecentTaskInfo> rawTasks =
-                mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
+        ArrayList<GroupedRecentTaskInfo> rawTasks;
+        try {
+            rawTasks = mSysUiProxy.getRecentTasks(Integer.MAX_VALUE, currentUserId);
+        } catch (SystemUiProxy.GetRecentTasksException e) {
+            rawTasks = new ArrayList<>();
+        }
         writer.println(prefix + "  rawTasks=[");
         for (GroupedRecentTaskInfo task : rawTasks) {
             TaskInfo taskInfo1 = task.getTaskInfo1();
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 66aa897..3f73959 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -1394,10 +1394,26 @@
         }
     }
 
-    public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+    public static class GetRecentTasksException extends Exception {
+        public GetRecentTasksException(String message) {
+            super(message);
+        }
+
+        public GetRecentTasksException(String message, Throwable cause) {
+            super(message, cause);
+        }
+    }
+
+    /**
+     * Retrieves a list of Recent tasks from ActivityManager.
+     * @throws GetRecentTasksException if IRecentTasks is not initialized, or when we get
+     * RemoteException from server side
+     */
+    public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId)
+            throws GetRecentTasksException {
         if (mRecentTasks == null) {
-            Log.w(TAG, "getRecentTasks() failed due to null mRecentTasks");
-            return new ArrayList<>();
+            Log.e(TAG, "getRecentTasks() failed due to null mRecentTasks");
+            throw new GetRecentTasksException("null mRecentTasks");
         }
         try {
             final GroupedRecentTaskInfo[] rawTasks = mRecentTasks.getRecentTasks(numTasks,
@@ -1407,8 +1423,8 @@
             }
             return new ArrayList<>(Arrays.asList(rawTasks));
         } catch (RemoteException e) {
-            Log.w(TAG, "Failed call getRecentTasks", e);
-            return new ArrayList<>();
+            Log.e(TAG, "Failed call getRecentTasks", e);
+            throw new GetRecentTasksException("Failed call getRecentTasks", e);
         }
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
index 5d00255..d049fbc 100644
--- a/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
+++ b/quickstep/tests/src/com/android/quickstep/RecentTasksListTest.java
@@ -16,6 +16,8 @@
 
 package com.android.quickstep;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static junit.framework.TestCase.assertNull;
 
 import static org.junit.Assert.assertEquals;
@@ -69,14 +71,14 @@
     }
 
     @Test
-    public void onRecentTasksChanged_doesNotFetchTasks() {
+    public void onRecentTasksChanged_doesNotFetchTasks() throws Exception {
         mRecentTasksList.onRecentTasksChanged();
         verify(mockSystemUiProxy, times(0))
                 .getRecentTasks(anyInt(), anyInt());
     }
 
     @Test
-    public void loadTasksInBackground_onlyKeys_noValidTaskDescription() {
+    public void loadTasksInBackground_onlyKeys_noValidTaskDescription() throws Exception  {
         GroupedRecentTaskInfo recentTaskInfos = GroupedRecentTaskInfo.forSplitTasks(
                 new ActivityManager.RecentTaskInfo(), new ActivityManager.RecentTaskInfo(), null);
         when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
@@ -91,7 +93,19 @@
     }
 
     @Test
-    public void loadTasksInBackground_moreThanKeys_hasValidTaskDescription() {
+    public void loadTasksInBackground_GetRecentTasksException() throws Exception  {
+        when(mockSystemUiProxy.getRecentTasks(anyInt(), anyInt()))
+                .thenThrow(new SystemUiProxy.GetRecentTasksException("task load failed"));
+
+        RecentTasksList.TaskLoadResult taskList = mRecentTasksList.loadTasksInBackground(
+                Integer.MAX_VALUE, -1, false);
+
+        assertThat(taskList.mRequestId).isEqualTo(-1);
+        assertThat(taskList).isEmpty();
+    }
+
+    @Test
+    public void loadTasksInBackground_moreThanKeys_hasValidTaskDescription() throws Exception  {
         String taskDescription = "Wheeee!";
         ActivityManager.RecentTaskInfo task1 = new ActivityManager.RecentTaskInfo();
         task1.taskDescription = new ActivityManager.TaskDescription(taskDescription);
@@ -111,7 +125,7 @@
     }
 
     @Test
-    public void loadTasksInBackground_freeformTask_createsDesktopTask() {
+    public void loadTasksInBackground_freeformTask_createsDesktopTask() throws Exception  {
         ActivityManager.RecentTaskInfo[] tasks = {
                 createRecentTaskInfo(1 /* taskId */),
                 createRecentTaskInfo(4 /* taskId */),
@@ -134,7 +148,8 @@
     }
 
     @Test
-    public void loadTasksInBackground_freeformTask_onlyMinimizedTasks_doesNotCreateDesktopTask() {
+    public void loadTasksInBackground_freeformTask_onlyMinimizedTasks_doesNotCreateDesktopTask()
+            throws Exception {
         ActivityManager.RecentTaskInfo[] tasks = {
                 createRecentTaskInfo(1 /* taskId */),
                 createRecentTaskInfo(4 /* taskId */),