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

Commit 2f906e94 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Fixing optimization in Task loading. (Bug 16372369)" into lmp-dev

parents 5d705ee6 ff88d7b3
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