Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff88d7b3 authored by Winson Chung's avatar Winson Chung
Browse files

Fixing optimization in Task loading. (Bug 16372369)

parent 9142a0f8
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.recents.misc;

import android.content.Intent;
import android.graphics.Color;
import android.graphics.Rect;
import com.android.systemui.recents.RecentsConfiguration;
@@ -93,4 +94,10 @@ public class Utilities {
            throws IllegalAccessException, InvocationTargetException {
        sPropertyMethod.invoke(null, property, value);
    }

    /** Returns whether the specified intent is a document. */
    public static boolean isDocument(Intent intent) {
        int flags = intent.getFlags();
        return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
    }
}
+20 −25
Original line number Diff line number Diff line
@@ -28,20 +28,20 @@ import java.util.HashMap;
public class KeyStoreLruCache<V> {
    // We keep a set of keys that are associated with the LRU cache, so that we can find out
    // information about the Task that was previously in the cache.
    HashMap<Task.TaskKey, Task.TaskKey> mKeys = new HashMap<Task.TaskKey, Task.TaskKey>();
    HashMap<Integer, Task.TaskKey> mTaskKeys = new HashMap<Integer, Task.TaskKey>();
    // The cache implementation
    LruCache<Task.TaskKey, V> mCache;
    LruCache<Integer, V> mCache;

    public KeyStoreLruCache(int cacheSize) {
        mCache = new LruCache<Task.TaskKey, V>(cacheSize) {
        mCache = new LruCache<Integer, V>(cacheSize) {
            @Override
            protected int sizeOf(Task.TaskKey t, V v) {
            protected int sizeOf(Integer taskId, V v) {
                return computeSize(v);
            }

            @Override
            protected void entryRemoved(boolean evicted, Task.TaskKey key, V oldV, V newV) {
                mKeys.remove(key);
            protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) {
                mTaskKeys.remove(taskId);
            }
        };
    }
@@ -53,46 +53,41 @@ public class KeyStoreLruCache<V> {

    /** Gets a specific entry in the cache. */
    final V get(Task.TaskKey key) {
        return mCache.get(key);
        return mCache.get(key.id);
    }

    /**
     * Returns the value only if the last active time of the key currently in the lru cache is
     * greater than or equal to the last active time of the key specified.
     * Returns the value only if the Task has not updated since the last time it was in the cache.
     */
    final V getCheckLastActiveTime(Task.TaskKey key) {
        Task.TaskKey lruKey = mKeys.get(key);
        if (lruKey != null && (lruKey.lastActiveTime < key.lastActiveTime)) {
            // The task has changed (been made active since the last time it was put into the
    final V getAndInvalidateIfModified(Task.TaskKey key) {
        Task.TaskKey lastKey = mTaskKeys.get(key.id);
        if (lastKey != null && (lastKey.lastActiveTime < key.lastActiveTime)) {
            // The task has updated (been made active since the last time it was put into the
            // LRU cache) so invalidate that item in the cache
            remove(lruKey);
            remove(key);
            return null;
        }
        // Either the task does not exist in the cache, or the last active time is the same as
        // the key specified
        return mCache.get(key);
        // the key specified, so return what is in the cache
        return mCache.get(key.id);
    }

    /** Puts an entry in the cache for a specific key. */
    final void put(Task.TaskKey key, V value) {
        mCache.put(key, value);
        if (mKeys.containsKey(key)) {
            mKeys.get(key).updateLastActiveTime(key.lastActiveTime);
        } else {
            mKeys.put(key, key);
        }
        mCache.put(key.id, value);
        mTaskKeys.put(key.id, key);
    }

    /** Removes a cache entry for a specific key. */
    final void remove(Task.TaskKey key) {
        mCache.remove(key);
        mKeys.remove(key);
        mCache.remove(key.id);
        mTaskKeys.remove(key.id);
    }

    /** Removes all the entries in the cache. */
    final void evictAll() {
        mCache.evictAll();
        mKeys.clear();
        mTaskKeys.clear();
    }

    /** Returns the size of the cache. */
+59 −64
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
@@ -41,6 +42,18 @@ import java.util.concurrent.ConcurrentLinkedQueue;
class TaskResourceLoadQueue {
    ConcurrentLinkedQueue<Task> mQueue = new ConcurrentLinkedQueue<Task>();

    /** Adds a new task to the load queue */
    void addTasks(Collection<Task> tasks) {
        for (Task t : tasks) {
            if (!mQueue.contains(t)) {
                mQueue.add(t);
            }
        }
        synchronized(this) {
            notifyAll();
        }
    }

    /** Adds a new task to the load queue */
    void addTask(Task t) {
        if (!mQueue.contains(t)) {
@@ -153,30 +166,30 @@ class TaskResourceLoader implements Runnable {
                // Load the next item from the queue
                final Task t = mLoadQueue.nextTask();
                if (t != null) {
                    Drawable cachedIcon = mApplicationIconCache.getCheckLastActiveTime(t.key);
                    Bitmap cachedThumbnail = mThumbnailCache.getCheckLastActiveTime(t.key);
                    Drawable cachedIcon = mApplicationIconCache.get(t.key);
                    Bitmap cachedThumbnail = mThumbnailCache.get(t.key);
                    // Load the application icon if it is stale or we haven't cached one yet
                    if (cachedIcon == null) {
                        Drawable icon = null;
                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
                                t.userId);
                        if (info != null) {
                            icon = ssp.getActivityIcon(info, t.userId);
                            cachedIcon = ssp.getActivityIcon(info, t.userId);
                        }
                        if (cachedIcon == null) {
                            cachedIcon = mDefaultApplicationIcon;
                        }
                        // If we can't load the icon, then set the default application icon into the
                        // cache.  This will remain until the task's last active time is updated.
                        cachedIcon = icon != null ? icon : mDefaultApplicationIcon;
                        // At this point, even if we can't load the icon, we will set the default
                        // icon.
                        mApplicationIconCache.put(t.key, cachedIcon);
                    }
                    // Load the thumbnail if it is stale or we haven't cached one yet
                    if (cachedThumbnail == null) {
                        Bitmap thumbnail = ssp.getTaskThumbnail(t.key.id);
                        if (thumbnail != null) {
                            thumbnail.setHasAlpha(false);
                        cachedThumbnail = ssp.getTaskThumbnail(t.key.id);
                        if (cachedThumbnail != null) {
                            cachedThumbnail.setHasAlpha(false);
                        } else {
                            cachedThumbnail = mDefaultThumbnail;
                        }
                        // Even if we can't load the icon, we set the default thumbnail into the
                        // cache.  This will remain until the task's last active time is updated.
                        cachedThumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail;
                        mThumbnailCache.put(t.key, cachedThumbnail);
                    }
                    if (!mCancelled) {
@@ -281,11 +294,11 @@ public class RecentsTaskLoader {
        return mSystemServicesProxy;
    }

    /** Gets the list of recent tasks, ordered from back to front. */
    private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp) {
        List<ActivityManager.RecentTaskInfo> tasks =
                ssp.getRecentTasks(50, UserHandle.CURRENT.getIdentifier());
        Collections.reverse(tasks);

        return tasks;
    }

@@ -302,7 +315,7 @@ public class RecentsTaskLoader {
        SystemServicesProxy ssp = mSystemServicesProxy;
        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp);

        // Add each task to the task stack
        // From back to front, add each task to the task stack
        int taskCount = tasks.size();
        for (int i = 0; i < taskCount; i++) {
            ActivityManager.RecentTaskInfo t = tasks.get(i);
@@ -311,7 +324,7 @@ public class RecentsTaskLoader {

            ActivityManager.TaskDescription av = t.taskDescription;
            String activityLabel = null;
            Drawable activityIcon = null;
            Drawable activityIcon = mDefaultApplicationIcon;
            int activityColor = config.taskBarViewDefaultBackgroundColor;
            if (av != null) {
                activityLabel = (av.getLabel() != null ? av.getLabel() : ssp.getActivityLabel(info));
@@ -323,7 +336,6 @@ public class RecentsTaskLoader {
            } else {
                activityLabel = ssp.getActivityLabel(info);
            }
            boolean isForemostTask = (i == (taskCount - 1));

            // Create a new task
            Task task = new Task(t.persistentId, (t.id > -1), t.baseIntent, t.affiliatedTaskId,
@@ -333,45 +345,36 @@ public class RecentsTaskLoader {
            // Preload the specified number of apps
            if (i >= (taskCount - preloadCount)) {
                // Load the icon from the cache if possible
                task.applicationIcon = mApplicationIconCache.getCheckLastActiveTime(task.key);
                task.applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(task.key);
                if (task.applicationIcon == null) {
                    if (isForemostTask) {
                        // We force loading the application icon for the foremost task
                    // Load the icon from the system
                    task.applicationIcon = ssp.getActivityIcon(info, task.userId);
                        if (task.applicationIcon == null) {
                            task.applicationIcon = mDefaultApplicationIcon;
                        }
                        // Even if we can't load the icon we set the default application icon into
                        // the cache.  This will remain until the task's last active time is updated.
                    if (task.applicationIcon != null) {
                        mApplicationIconCache.put(task.key, task.applicationIcon);
                    } else {
                    }
                }
                if (task.applicationIcon == null) {
                    // Either the task has changed since the last active time, or it was not
                    // previously cached, so try and load the task anew.
                    tasksToLoad.add(task);
                }
                }

                // Load the thumbnail (if possible and not the foremost task, from the cache)
                task.thumbnail = mThumbnailCache.getCheckLastActiveTime(task.key);
                // Load the thumbnail from the cache if possible
                task.thumbnail = mThumbnailCache.getAndInvalidateIfModified(task.key);
                if (task.thumbnail == null) {
                    if (isForemostTask) {
                        // We force loading the thumbnail icon for the foremost task
                    // Load the thumbnail from the system
                    task.thumbnail = ssp.getTaskThumbnail(task.key.id);
                    if (task.thumbnail != null) {
                        task.thumbnail.setHasAlpha(false);
                        } else {
                            task.thumbnail = mDefaultThumbnail;
                        }
                        // Even if we can't load the thumbnail we set the default thumbnail into
                        // the cache.  This will remain until the task's last active time is updated.
                        mThumbnailCache.put(task.key, task.thumbnail);
                    } else {
                    }
                }
                if (task.thumbnail == null) {
                    // Either the task has changed since the last active time, or it was not
                    // previously cached, so try and load the task anew.
                    tasksToLoad.add(task);
                }
            }
            }

            // Add the task to the stack
            stack.addTask(task);
@@ -380,13 +383,9 @@ public class RecentsTaskLoader {
        // Simulate the groupings that we describe
        stack.createAffiliatedGroupings();

        // Start the task loader
        // Start the task loader and add all the tasks we need to load
        mLoader.start(context);

        // Add all the tasks that we are reloading
        for (Task t : tasksToLoad) {
            mLoadQueue.addTask(t);
        }
        mLoadQueue.addTasks(tasksToLoad);

        // Update the package monitor with the list of packages to listen for
        mPackageMonitor.setTasks(tasks);
@@ -414,18 +413,14 @@ public class RecentsTaskLoader {

    /** Acquires the task resource data directly from the pool. */
    public void loadTaskData(Task t) {
        Drawable applicationIcon = mApplicationIconCache.get(t.key);
        Bitmap thumbnail = mThumbnailCache.get(t.key);

        boolean requiresLoad = false;
        if (applicationIcon == null) {
            applicationIcon = mDefaultApplicationIcon;
            requiresLoad = true;
        }
        if (thumbnail == null) {
            thumbnail = mLoadingThumbnail;
            requiresLoad = true;
        }
        Drawable applicationIcon = mApplicationIconCache.getAndInvalidateIfModified(t.key);
        Bitmap thumbnail = mThumbnailCache.getAndInvalidateIfModified(t.key);

        // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and
        // use the default assets in their place until they load
        boolean requiresLoad = (applicationIcon == null) || (thumbnail == null);
        applicationIcon = applicationIcon != null ? applicationIcon : mDefaultApplicationIcon;
        thumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail;
        if (requiresLoad) {
            mLoadQueue.addTask(t);
        }
+0 −4
Original line number Diff line number Diff line
@@ -51,10 +51,6 @@ public class Task {
            this.lastActiveTime = lastActiveTime;
        }

        public void updateLastActiveTime(long lastActiveTime) {
            this.lastActiveTime = lastActiveTime;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof TaskKey)) {
+3 −5
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.SpaceNode;
@@ -458,7 +459,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
                    Intent i = new Intent(task.key.baseIntent);
                    i.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
                            | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
                    if ((i.getFlags() & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == 0) {
                    if (!Utilities.isDocument(i)) {
                        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    }
                    try {
@@ -510,11 +511,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
        loader.deleteTaskData(t, false);

        // Remove the old task from activity manager
        int flags = t.key.baseIntent.getFlags();
        boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
                Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
        RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
                isDocument);
                Utilities.isDocument(t.key.baseIntent));
    }

    @Override