Ensuring that the ActivityInfo cache accounts for the task's user id. (Bug 17314317)

Change-Id: I10bcb60abe3450f2ecfb3ee305be505e13e0be3b
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index a93e244..f7ad35b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -18,7 +18,6 @@
 
 import android.app.ActivityManager;
 import android.content.ComponentCallbacks2;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Resources;
@@ -28,6 +27,8 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.UserHandle;
+import android.util.Log;
+
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -232,6 +233,8 @@
 /* Recents task loader
  * NOTE: We should not hold any references to a Context from a static instance */
 public class RecentsTaskLoader {
+    private static final String TAG = "RecentsTaskLoader";
+
     static RecentsTaskLoader sInstance;
 
     SystemServicesProxy mSystemServicesProxy;
@@ -335,11 +338,15 @@
                 infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(),
                         taskKey.userId);
             }
-            icon = ssp.getActivityIcon(infoHandle.info, taskKey.userId);
-            mApplicationIconCache.put(taskKey, icon);
-            return icon;
+            if (infoHandle.info != null) {
+                icon = ssp.getActivityIcon(infoHandle.info, taskKey.userId);
+                if (icon != null) {
+                    mApplicationIconCache.put(taskKey, icon);
+                    return icon;
+                }
+            }
         }
-        // If we are not preloading, return the default icon to show
+        // If we couldn't load any icon, return null
         return null;
     }
 
@@ -361,8 +368,13 @@
             infoHandle.info = ssp.getActivityInfo(taskKey.baseIntent.getComponent(),
                     taskKey.userId);
         }
-        label = ssp.getActivityLabel(infoHandle.info);
-        mActivityLabelCache.put(taskKey, label);
+        if (infoHandle.info != null) {
+            label = ssp.getActivityLabel(infoHandle.info);
+            mActivityLabelCache.put(taskKey, label);
+        } else {
+            Log.w(TAG, "Missing ActivityInfo for " + taskKey.baseIntent.getComponent()
+                    + " u=" + taskKey.userId);
+        }
         return label;
     }
 
@@ -401,8 +413,8 @@
             List<Task> tasksToLoadOut) {
         RecentsConfiguration config = RecentsConfiguration.getInstance();
         List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp);
-        HashMap<ComponentName, ActivityInfoHandle> activityInfoCache =
-                new HashMap<ComponentName, ActivityInfoHandle>();
+        HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
+                new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
         ArrayList<Task> tasksToAdd = new ArrayList<Task>();
         TaskStack stack = new TaskStack();
 
@@ -410,19 +422,21 @@
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = tasks.get(i);
 
-            // Get an existing activity info handle if possible
-            ComponentName cn = t.baseIntent.getComponent();
-            ActivityInfoHandle infoHandle = new ActivityInfoHandle();
-            boolean hasCachedActivityInfo = false;
-            if (activityInfoCache.containsKey(cn)) {
-                infoHandle = activityInfoCache.get(cn);
-                hasCachedActivityInfo = true;
-            }
-
             // Compose the task key
             Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.baseIntent, t.userId,
                     t.firstActiveTime, t.lastActiveTime);
 
+            // Get an existing activity info handle if possible
+            Task.ComponentNameKey cnKey = taskKey.getComponentNameKey();
+            ActivityInfoHandle infoHandle;
+            boolean hasCachedActivityInfo = false;
+            if (activityInfoCache.containsKey(cnKey)) {
+                infoHandle = activityInfoCache.get(cnKey);
+                hasCachedActivityInfo = true;
+            } else {
+                infoHandle = new ActivityInfoHandle();
+            }
+
             // Determine whether to preload this task
             boolean preloadTask = false;
             if (preloadTaskId > 0) {
@@ -440,7 +454,7 @@
 
             // Update the activity info cache
             if (!hasCachedActivityInfo && infoHandle.info != null) {
-                activityInfoCache.put(cn, infoHandle);
+                activityInfoCache.put(cnKey, infoHandle);
             }
 
             // Add the task to the stack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 977db60..406e03f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -16,12 +16,15 @@
 
 package com.android.systemui.recents.model;
 
+import android.content.ComponentName;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import com.android.systemui.recents.misc.Utilities;
 
+import java.util.Objects;
+
 
 /**
  * A task represents the top most task in the system's task stack.
@@ -35,8 +38,35 @@
         public void onTaskDataUnloaded();
     }
 
+    /** The ComponentNameKey represents the unique primary key for a component
+     * belonging to a specified user. */
+    public static class ComponentNameKey {
+        final ComponentName component;
+        final int userId;
+
+        public ComponentNameKey(ComponentName cn, int user) {
+            component = cn;
+            userId = user;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(component, userId);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof ComponentNameKey)) {
+                return false;
+            }
+            return component.equals(((ComponentNameKey) o).component) &&
+                    userId == ((ComponentNameKey) o).userId;
+        }
+    }
+
     /* The Task Key represents the unique primary key for the task */
     public static class TaskKey {
+        final ComponentNameKey mComponentNameKey;
         public final int id;
         public final Intent baseIntent;
         public final int userId;
@@ -44,6 +74,7 @@
         public long lastActiveTime;
 
         public TaskKey(int id, Intent intent, int userId, long firstActiveTime, long lastActiveTime) {
+            mComponentNameKey = new ComponentNameKey(intent.getComponent(), userId);
             this.id = id;
             this.baseIntent = intent;
             this.userId = userId;
@@ -51,6 +82,11 @@
             this.lastActiveTime = lastActiveTime;
         }
 
+        /** Returns the component name key for this task. */
+        public ComponentNameKey getComponentNameKey() {
+            return mComponentNameKey;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (!(o instanceof TaskKey)) {