Loading packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +40 −16 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport; import com.android.systemui.recents.views.TaskStackView; import com.android.systemui.recents.views.TaskStackViewScroller; import com.android.systemui.recents.views.TaskViewHeader; Loading Loading @@ -126,11 +127,22 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener if (runningTaskInfo != null) { launchOpts.runningTaskId = runningTaskInfo.id; } launchOpts.numVisibleTasks = 2; launchOpts.numVisibleTaskThumbnails = 2; mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */); updateDummyStackViewLayout(plan.getTaskStack(), getWindowRect(null /* windowRectOverride */)); // Launched from app is always the worst case (in terms of how many thumbnails/tasks // visible) RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); launchState.launchedFromApp = true; mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState); VisibilityReport visibilityReport = mDummyStackView.computeStackVisibilityReport(); launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks; launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails; launchOpts.onlyLoadForCache = true; launchOpts.onlyLoadPausedActivities = true; launchOpts.loadThumbnails = !ActivityManager.ENABLE_TASK_SNAPSHOTS; launchOpts.loadThumbnails = true; loader.loadTasks(mContext, plan, launchOpts); } } Loading Loading @@ -605,23 +617,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection()); } /** * Prepares the header bar layout for the next transition, if the task view bounds has changed * since the last call, it will attempt to re-measure and layout the header bar to the new size. * * @param stack the stack to initialize the stack layout with * @param windowRectOverride the rectangle to use when calculating the stack state which can * be different from the current window rect if recents is resizing * while being launched */ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { private void updateDummyStackViewLayout(TaskStack stack, Rect windowRect) { SystemServicesProxy ssp = Recents.getSystemServices(); Rect displayRect = ssp.getDisplayRect(); Rect systemInsets = new Rect(); ssp.getStableInsets(systemInsets); Rect windowRect = windowRectOverride != null ? new Rect(windowRectOverride) : ssp.getWindowRect(); // When docked, the nav bar insets are consumed and the activity is measured without insets. // However, the window bounds include the insets, so we need to subtract them here to make // them identical. Loading @@ -642,6 +643,29 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener stackLayout.reset(); stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); } } private Rect getWindowRect(Rect windowRectOverride) { return windowRectOverride != null ? new Rect(windowRectOverride) : Recents.getSystemServices().getWindowRect(); } /** * Prepares the header bar layout for the next transition, if the task view bounds has changed * since the last call, it will attempt to re-measure and layout the header bar to the new size. * * @param stack the stack to initialize the stack layout with * @param windowRectOverride the rectangle to use when calculating the stack state which can * be different from the current window rect if recents is resizing * while being launched */ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { Rect windowRect = getWindowRect(windowRectOverride); updateDummyStackViewLayout(stack, windowRect); if (stack != null) { TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); // Get the width of a task view so that we know how wide to draw the header bar. int taskViewWidth = 0; Loading packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +1 −2 Original line number Diff line number Diff line Loading @@ -671,8 +671,7 @@ public class SystemServicesProxy { if (ActivityManager.ENABLE_TASK_SNAPSHOTS) { ActivityManager.TaskSnapshot snapshot = null; try { snapshot = ActivityManager.getService().getTaskSnapshot(taskId, false /* reducedResolution */); snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution); } catch (RemoteException e) { Log.w(TAG, "Failed to retrieve snapshot", e); } Loading packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +6 −14 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ public class RecentsTaskLoadPlan { public static class Options { public int runningTaskId = -1; public boolean loadIcons = true; public boolean loadThumbnails = true; public boolean loadThumbnails = false; public boolean onlyLoadForCache = false; public boolean onlyLoadPausedActivities = false; public int numVisibleTasks = 0; Loading Loading @@ -189,7 +189,7 @@ public class RecentsTaskLoadPlan { ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false) : null; ThumbnailData thumbnail = loader.getAndUpdateThumbnail(taskKey, false /* loadIfNotCached */); false /* loadIfNotCached */, false /* storeInCache */); int activityColor = loader.getActivityPrimaryColor(t.taskDescription); int backgroundColor = loader.getActivityBackgroundColor(t.taskDescription); boolean isSystemApp = (info != null) && Loading Loading @@ -223,9 +223,7 @@ public class RecentsTaskLoadPlan { /** * Called to apply the actual loading based on the specified conditions. */ public synchronized void executePlan(Options opts, RecentsTaskLoader loader, TaskResourceLoadQueue loadQueue) { RecentsConfiguration config = Recents.getConfiguration(); public synchronized void executePlan(Options opts, RecentsTaskLoader loader) { Resources res = mContext.getResources(); // Iterate through each of the tasks and load them according to the load conditions. Loading @@ -250,15 +248,9 @@ public class RecentsTaskLoadPlan { true); } } if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) { if (task.thumbnail == null || isRunningTask) { if (config.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) { if (opts.loadThumbnails && isVisibleThumbnail) { task.thumbnail = loader.getAndUpdateThumbnail(taskKey, true /* loadIfNotCached */); } else if (config.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) { loadQueue.addTask(task); } } true /* loadIfNotCached */, true /* storeInCache */); } } } Loading packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +34 −9 Original line number Diff line number Diff line Loading @@ -37,8 +37,6 @@ import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.events.activity.PackagesChangedEvent; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task.TaskKey; import java.io.PrintWriter; import java.util.Map; Loading Loading @@ -245,11 +243,11 @@ public class RecentsTaskLoader { private final TaskResourceLoadQueue mLoadQueue; private final BackgroundTaskLoader mLoader; private final HighResThumbnailLoader mHighResThumbnailLoader; private final TaskKeyStrongCache<ThumbnailData> mThumbnailCache = new TaskKeyStrongCache<>(); private final TaskKeyStrongCache<ThumbnailData> mTempCache = new TaskKeyStrongCache<>(); private final int mMaxThumbnailCacheSize; private final int mMaxIconCacheSize; private int mNumVisibleTasksLoaded; private int mNumVisibleThumbnailsLoaded; int mDefaultTaskBarBackgroundColor; int mDefaultTaskViewBackgroundColor; Loading Loading @@ -332,10 +330,19 @@ public class RecentsTaskLoader { if (opts == null) { throw new RuntimeException("Requires load options"); } plan.executePlan(opts, this, mLoadQueue); if (opts.onlyLoadForCache && opts.loadThumbnails) { // If we are loading for the cache, we'd like to have the real cache only include the // visible thumbnails. However, we also don't want to reload already cached thumbnails. // Thus, we copy over the current entries into a second cache, and clear the real cache, // such that the real cache only contains visible thumbnails. mTempCache.copyEntries(mThumbnailCache); mThumbnailCache.evictAll(); } plan.executePlan(opts, this); mTempCache.evictAll(); if (!opts.onlyLoadForCache) { mNumVisibleTasksLoaded = opts.numVisibleTasks; mNumVisibleThumbnailsLoaded = opts.numVisibleTaskThumbnails; // Start the loader mLoader.start(context); Loading @@ -349,7 +356,7 @@ public class RecentsTaskLoader { Drawable icon = mIconCache.getAndInvalidateIfModified(t.key); icon = icon != null ? icon : mDefaultIcon; mLoadQueue.addTask(t); t.notifyTaskDataLoaded(null, icon); t.notifyTaskDataLoaded(t.thumbnail, icon); } /** Releases the task resource data back into the pool. */ Loading Loading @@ -404,6 +411,7 @@ public class RecentsTaskLoader { // The cache is small, only clear the label cache when we are critical mActivityLabelCache.evictAll(); mContentDescriptionCache.evictAll(); mThumbnailCache.evictAll(); break; default: break; Loading Loading @@ -500,15 +508,31 @@ public class RecentsTaskLoader { /** * Returns the cached thumbnail if the task key is not expired, updating the cache if it is. */ ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) { ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached, boolean storeInCache) { SystemServicesProxy ssp = Recents.getSystemServices(); ThumbnailData cached = mThumbnailCache.getAndInvalidateIfModified(taskKey); if (cached != null) { return cached; } cached = mTempCache.getAndInvalidateIfModified(taskKey); if (cached != null) { mThumbnailCache.put(taskKey, cached); return cached; } if (loadIfNotCached) { RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) { // Load the thumbnail from the system ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id, true /* reducedResolution */); ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id, true /* reducedResolution */); if (thumbnailData.thumbnail != null) { if (storeInCache) { mThumbnailCache.put(taskKey, thumbnailData); } return thumbnailData; } } Loading Loading @@ -590,5 +614,6 @@ public class RecentsTaskLoader { writer.print(prefix); writer.println(TAG); writer.print(prefix); writer.println("Icon Cache"); mIconCache.dump(innerPrefix, writer); mThumbnailCache.dump(innerPrefix, writer); } } packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyCache.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.recents.model; import android.util.Log; import android.util.SparseArray; import com.android.systemui.recents.model.Task.TaskKey; /** * Base class for both strong and LRU task key cache. */ public abstract class TaskKeyCache<V> { protected static final String TAG = "TaskKeyCache"; protected final SparseArray<TaskKey> mKeys = new SparseArray<>(); /** * Gets a specific entry in the cache with the specified key, regardless of whether the cached * value is valid or not. */ final V get(Task.TaskKey key) { return getCacheEntry(key.id); } /** * Returns the value only if the key is valid (has not been updated since the last time it was * in the cache) */ final V getAndInvalidateIfModified(Task.TaskKey key) { Task.TaskKey lastKey = mKeys.get(key.id); if (lastKey != null) { if ((lastKey.stackId != key.stackId) || (lastKey.lastActiveTime != key.lastActiveTime)) { // The task has updated (been made active since the last time it was put into the // LRU cache) or the stack id for the task has changed, invalidate that cache item 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, so return what is in the cache return getCacheEntry(key.id); } /** Puts an entry in the cache for a specific key. */ final void put(Task.TaskKey key, V value) { if (key == null || value == null) { Log.e(TAG, "Unexpected null key or value: " + key + ", " + value); return; } mKeys.put(key.id, key); putCacheEntry(key.id, value); } /** Removes a cache entry for a specific key. */ final void remove(Task.TaskKey key) { // Remove the key after the cache value because we need it to make the callback removeCacheEntry(key.id); mKeys.remove(key.id); } /** Removes all the entries in the cache. */ final void evictAll() { evictAllCache(); mKeys.clear(); } protected abstract V getCacheEntry(int id); protected abstract void putCacheEntry(int id, V value); protected abstract void removeCacheEntry(int id); protected abstract void evictAllCache(); } Loading
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +40 −16 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport; import com.android.systemui.recents.views.TaskStackView; import com.android.systemui.recents.views.TaskStackViewScroller; import com.android.systemui.recents.views.TaskViewHeader; Loading Loading @@ -126,11 +127,22 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener if (runningTaskInfo != null) { launchOpts.runningTaskId = runningTaskInfo.id; } launchOpts.numVisibleTasks = 2; launchOpts.numVisibleTaskThumbnails = 2; mDummyStackView.setTasks(plan.getTaskStack(), false /* allowNotify */); updateDummyStackViewLayout(plan.getTaskStack(), getWindowRect(null /* windowRectOverride */)); // Launched from app is always the worst case (in terms of how many thumbnails/tasks // visible) RecentsActivityLaunchState launchState = new RecentsActivityLaunchState(); launchState.launchedFromApp = true; mDummyStackView.updateLayoutAlgorithm(true /* boundScroll */, launchState); VisibilityReport visibilityReport = mDummyStackView.computeStackVisibilityReport(); launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks; launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails; launchOpts.onlyLoadForCache = true; launchOpts.onlyLoadPausedActivities = true; launchOpts.loadThumbnails = !ActivityManager.ENABLE_TASK_SNAPSHOTS; launchOpts.loadThumbnails = true; loader.loadTasks(mContext, plan, launchOpts); } } Loading Loading @@ -605,23 +617,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection()); } /** * Prepares the header bar layout for the next transition, if the task view bounds has changed * since the last call, it will attempt to re-measure and layout the header bar to the new size. * * @param stack the stack to initialize the stack layout with * @param windowRectOverride the rectangle to use when calculating the stack state which can * be different from the current window rect if recents is resizing * while being launched */ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { private void updateDummyStackViewLayout(TaskStack stack, Rect windowRect) { SystemServicesProxy ssp = Recents.getSystemServices(); Rect displayRect = ssp.getDisplayRect(); Rect systemInsets = new Rect(); ssp.getStableInsets(systemInsets); Rect windowRect = windowRectOverride != null ? new Rect(windowRectOverride) : ssp.getWindowRect(); // When docked, the nav bar insets are consumed and the activity is measured without insets. // However, the window bounds include the insets, so we need to subtract them here to make // them identical. Loading @@ -642,6 +643,29 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener stackLayout.reset(); stackLayout.initialize(displayRect, windowRect, mTaskStackBounds, TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack)); } } private Rect getWindowRect(Rect windowRectOverride) { return windowRectOverride != null ? new Rect(windowRectOverride) : Recents.getSystemServices().getWindowRect(); } /** * Prepares the header bar layout for the next transition, if the task view bounds has changed * since the last call, it will attempt to re-measure and layout the header bar to the new size. * * @param stack the stack to initialize the stack layout with * @param windowRectOverride the rectangle to use when calculating the stack state which can * be different from the current window rect if recents is resizing * while being launched */ private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) { Rect windowRect = getWindowRect(windowRectOverride); updateDummyStackViewLayout(stack, windowRect); if (stack != null) { TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm(); mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */); // Get the width of a task view so that we know how wide to draw the header bar. int taskViewWidth = 0; Loading
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +1 −2 Original line number Diff line number Diff line Loading @@ -671,8 +671,7 @@ public class SystemServicesProxy { if (ActivityManager.ENABLE_TASK_SNAPSHOTS) { ActivityManager.TaskSnapshot snapshot = null; try { snapshot = ActivityManager.getService().getTaskSnapshot(taskId, false /* reducedResolution */); snapshot = ActivityManager.getService().getTaskSnapshot(taskId, reducedResolution); } catch (RemoteException e) { Log.w(TAG, "Failed to retrieve snapshot", e); } Loading
packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +6 −14 Original line number Diff line number Diff line Loading @@ -64,7 +64,7 @@ public class RecentsTaskLoadPlan { public static class Options { public int runningTaskId = -1; public boolean loadIcons = true; public boolean loadThumbnails = true; public boolean loadThumbnails = false; public boolean onlyLoadForCache = false; public boolean onlyLoadPausedActivities = false; public int numVisibleTasks = 0; Loading Loading @@ -189,7 +189,7 @@ public class RecentsTaskLoadPlan { ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false) : null; ThumbnailData thumbnail = loader.getAndUpdateThumbnail(taskKey, false /* loadIfNotCached */); false /* loadIfNotCached */, false /* storeInCache */); int activityColor = loader.getActivityPrimaryColor(t.taskDescription); int backgroundColor = loader.getActivityBackgroundColor(t.taskDescription); boolean isSystemApp = (info != null) && Loading Loading @@ -223,9 +223,7 @@ public class RecentsTaskLoadPlan { /** * Called to apply the actual loading based on the specified conditions. */ public synchronized void executePlan(Options opts, RecentsTaskLoader loader, TaskResourceLoadQueue loadQueue) { RecentsConfiguration config = Recents.getConfiguration(); public synchronized void executePlan(Options opts, RecentsTaskLoader loader) { Resources res = mContext.getResources(); // Iterate through each of the tasks and load them according to the load conditions. Loading @@ -250,15 +248,9 @@ public class RecentsTaskLoadPlan { true); } } if (opts.loadThumbnails && (isRunningTask || isVisibleThumbnail)) { if (task.thumbnail == null || isRunningTask) { if (config.svelteLevel <= RecentsConfiguration.SVELTE_LIMIT_CACHE) { if (opts.loadThumbnails && isVisibleThumbnail) { task.thumbnail = loader.getAndUpdateThumbnail(taskKey, true /* loadIfNotCached */); } else if (config.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) { loadQueue.addTask(task); } } true /* loadIfNotCached */, true /* storeInCache */); } } } Loading
packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +34 −9 Original line number Diff line number Diff line Loading @@ -37,8 +37,6 @@ import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.events.activity.PackagesChangedEvent; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task.TaskKey; import java.io.PrintWriter; import java.util.Map; Loading Loading @@ -245,11 +243,11 @@ public class RecentsTaskLoader { private final TaskResourceLoadQueue mLoadQueue; private final BackgroundTaskLoader mLoader; private final HighResThumbnailLoader mHighResThumbnailLoader; private final TaskKeyStrongCache<ThumbnailData> mThumbnailCache = new TaskKeyStrongCache<>(); private final TaskKeyStrongCache<ThumbnailData> mTempCache = new TaskKeyStrongCache<>(); private final int mMaxThumbnailCacheSize; private final int mMaxIconCacheSize; private int mNumVisibleTasksLoaded; private int mNumVisibleThumbnailsLoaded; int mDefaultTaskBarBackgroundColor; int mDefaultTaskViewBackgroundColor; Loading Loading @@ -332,10 +330,19 @@ public class RecentsTaskLoader { if (opts == null) { throw new RuntimeException("Requires load options"); } plan.executePlan(opts, this, mLoadQueue); if (opts.onlyLoadForCache && opts.loadThumbnails) { // If we are loading for the cache, we'd like to have the real cache only include the // visible thumbnails. However, we also don't want to reload already cached thumbnails. // Thus, we copy over the current entries into a second cache, and clear the real cache, // such that the real cache only contains visible thumbnails. mTempCache.copyEntries(mThumbnailCache); mThumbnailCache.evictAll(); } plan.executePlan(opts, this); mTempCache.evictAll(); if (!opts.onlyLoadForCache) { mNumVisibleTasksLoaded = opts.numVisibleTasks; mNumVisibleThumbnailsLoaded = opts.numVisibleTaskThumbnails; // Start the loader mLoader.start(context); Loading @@ -349,7 +356,7 @@ public class RecentsTaskLoader { Drawable icon = mIconCache.getAndInvalidateIfModified(t.key); icon = icon != null ? icon : mDefaultIcon; mLoadQueue.addTask(t); t.notifyTaskDataLoaded(null, icon); t.notifyTaskDataLoaded(t.thumbnail, icon); } /** Releases the task resource data back into the pool. */ Loading Loading @@ -404,6 +411,7 @@ public class RecentsTaskLoader { // The cache is small, only clear the label cache when we are critical mActivityLabelCache.evictAll(); mContentDescriptionCache.evictAll(); mThumbnailCache.evictAll(); break; default: break; Loading Loading @@ -500,15 +508,31 @@ public class RecentsTaskLoader { /** * Returns the cached thumbnail if the task key is not expired, updating the cache if it is. */ ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached) { ThumbnailData getAndUpdateThumbnail(Task.TaskKey taskKey, boolean loadIfNotCached, boolean storeInCache) { SystemServicesProxy ssp = Recents.getSystemServices(); ThumbnailData cached = mThumbnailCache.getAndInvalidateIfModified(taskKey); if (cached != null) { return cached; } cached = mTempCache.getAndInvalidateIfModified(taskKey); if (cached != null) { mThumbnailCache.put(taskKey, cached); return cached; } if (loadIfNotCached) { RecentsConfiguration config = Recents.getConfiguration(); if (config.svelteLevel < RecentsConfiguration.SVELTE_DISABLE_LOADING) { // Load the thumbnail from the system ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id, true /* reducedResolution */); ThumbnailData thumbnailData = ssp.getTaskThumbnail(taskKey.id, true /* reducedResolution */); if (thumbnailData.thumbnail != null) { if (storeInCache) { mThumbnailCache.put(taskKey, thumbnailData); } return thumbnailData; } } Loading Loading @@ -590,5 +614,6 @@ public class RecentsTaskLoader { writer.print(prefix); writer.println(TAG); writer.print(prefix); writer.println("Icon Cache"); mIconCache.dump(innerPrefix, writer); mThumbnailCache.dump(innerPrefix, writer); } }
packages/SystemUI/src/com/android/systemui/recents/model/TaskKeyCache.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package com.android.systemui.recents.model; import android.util.Log; import android.util.SparseArray; import com.android.systemui.recents.model.Task.TaskKey; /** * Base class for both strong and LRU task key cache. */ public abstract class TaskKeyCache<V> { protected static final String TAG = "TaskKeyCache"; protected final SparseArray<TaskKey> mKeys = new SparseArray<>(); /** * Gets a specific entry in the cache with the specified key, regardless of whether the cached * value is valid or not. */ final V get(Task.TaskKey key) { return getCacheEntry(key.id); } /** * Returns the value only if the key is valid (has not been updated since the last time it was * in the cache) */ final V getAndInvalidateIfModified(Task.TaskKey key) { Task.TaskKey lastKey = mKeys.get(key.id); if (lastKey != null) { if ((lastKey.stackId != key.stackId) || (lastKey.lastActiveTime != key.lastActiveTime)) { // The task has updated (been made active since the last time it was put into the // LRU cache) or the stack id for the task has changed, invalidate that cache item 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, so return what is in the cache return getCacheEntry(key.id); } /** Puts an entry in the cache for a specific key. */ final void put(Task.TaskKey key, V value) { if (key == null || value == null) { Log.e(TAG, "Unexpected null key or value: " + key + ", " + value); return; } mKeys.put(key.id, key); putCacheEntry(key.id, value); } /** Removes a cache entry for a specific key. */ final void remove(Task.TaskKey key) { // Remove the key after the cache value because we need it to make the callback removeCacheEntry(key.id); mKeys.remove(key.id); } /** Removes all the entries in the cache. */ final void evictAll() { evictAllCache(); mKeys.clear(); } protected abstract V getCacheEntry(int id); protected abstract void putCacheEntry(int id, V value); protected abstract void removeCacheEntry(int id); protected abstract void evictAllCache(); }