Merge "Improve caching behavior of thumbnails" into oc-dev

am: b67e105e74

Change-Id: I48914589de80ca11c97919bb5af6903ae46d2b3f
This commit is contained in:
Jorim Jaggi
2017-04-12 00:01:41 +00:00
committed by android-build-merger
12 changed files with 303 additions and 163 deletions

View File

@@ -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;
@@ -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);
}
}
@@ -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.
@@ -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;

View File

@@ -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);
}

View File

@@ -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;
@@ -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) &&
@@ -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.
@@ -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) {
task.thumbnail = loader.getAndUpdateThumbnail(taskKey,
true /* loadIfNotCached */);
} else if (config.svelteLevel == RecentsConfiguration.SVELTE_DISABLE_CACHE) {
loadQueue.addTask(task);
}
}
if (opts.loadThumbnails && isVisibleThumbnail) {
task.thumbnail = loader.getAndUpdateThumbnail(taskKey,
true /* loadIfNotCached */, true /* storeInCache */);
}
}
}

View File

@@ -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;
@@ -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;
@@ -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);
@@ -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. */
@@ -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;
@@ -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;
}
}
@@ -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);
}
}

View File

@@ -0,0 +1,89 @@
/*
* 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();
}

View File

@@ -16,12 +16,9 @@
package com.android.systemui.recents.model;
import android.util.Log;
import android.util.LruCache;
import android.util.SparseArray;
import java.io.PrintWriter;
import java.util.ArrayList;
/**
* A mapping of {@link Task.TaskKey} to value, with additional LRU functionality where the least
@@ -31,15 +28,12 @@ import java.util.ArrayList;
* In addition, this also allows the caller to invalidate cached values for keys that have since
* changed.
*/
public class TaskKeyLruCache<V> {
public class TaskKeyLruCache<V> extends TaskKeyCache<V> {
public interface EvictionCallback {
public void onEntryEvicted(Task.TaskKey key);
}
private static final String TAG = "TaskKeyLruCache";
private final SparseArray<Task.TaskKey> mKeys = new SparseArray<>();
private final LruCache<Integer, V> mCache;
private final EvictionCallback mEvictionCallback;
@@ -61,57 +55,6 @@ public class TaskKeyLruCache<V> {
};
}
/**
* 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 mCache.get(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 mCache.get(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);
mCache.put(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
mCache.remove(key.id);
mKeys.remove(key.id);
}
/** Removes all the entries in the cache. */
final void evictAll() {
mCache.evictAll();
mKeys.clear();
}
/** Trims the cache to a specific size */
final void trimToSize(int cacheSize) {
mCache.trimToSize(cacheSize);
@@ -128,4 +71,24 @@ public class TaskKeyLruCache<V> {
writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i)));
}
}
@Override
protected V getCacheEntry(int id) {
return mCache.get(id);
}
@Override
protected void putCacheEntry(int id, V value) {
mCache.put(id, value);
}
@Override
protected void removeCacheEntry(int id) {
mCache.remove(id);
}
@Override
protected void evictAllCache() {
mCache.evictAll();
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
import com.android.systemui.recents.model.Task.TaskKey;
import java.io.PrintWriter;
/**
* Like {@link TaskKeyLruCache}, but without LRU functionality.
*/
public class TaskKeyStrongCache<V> extends TaskKeyCache<V> {
private static final String TAG = "TaskKeyCache";
private final ArrayMap<Integer, V> mCache = new ArrayMap<>();
final void copyEntries(TaskKeyStrongCache<V> other) {
for (int i = other.mKeys.size() - 1; i >= 0; i--) {
TaskKey key = other.mKeys.valueAt(i);
put(key, other.mCache.get(key.id));
}
}
public void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.print(prefix); writer.print(TAG);
writer.print(" numEntries="); writer.print(mKeys.size());
writer.println();
int keyCount = mKeys.size();
for (int i = 0; i < keyCount; i++) {
writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i)));
}
}
@Override
protected V getCacheEntry(int id) {
return mCache.get(id);
}
@Override
protected void putCacheEntry(int id, V value) {
mCache.put(id, value);
}
@Override
protected void removeCacheEntry(int id) {
mCache.remove(id);
}
@Override
protected void evictAllCache() {
mCache.clear();
}
}

View File

@@ -220,12 +220,11 @@ public class TaskStackLayoutAlgorithm {
}
// A report of the visibility state of the stack
public class VisibilityReport {
public static class VisibilityReport {
public int numVisibleTasks;
public int numVisibleThumbnails;
/** Package level ctor */
VisibilityReport(int tasks, int thumbnails) {
public VisibilityReport(int tasks, int thumbnails) {
numVisibleTasks = tasks;
numVisibleThumbnails = thumbnails;
}
@@ -505,9 +504,9 @@ public class TaskStackLayoutAlgorithm {
* Computes the minimum and maximum scroll progress values and the progress values for each task
* in the stack.
*/
void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet) {
void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet,
RecentsActivityLaunchState launchState) {
SystemServicesProxy ssp = Recents.getSystemServices();
RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
// Clear the progress map
mTaskIndexMap.clear();
@@ -788,6 +787,10 @@ public class TaskStackLayoutAlgorithm {
* stack scroll. Requires that update() is called first.
*/
public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
if (useGridLayout()) {
return mTaskGridLayoutAlgorithm.computeStackVisibilityReport(tasks);
}
// Ensure minimum visibility count
if (tasks.size() <= 1) {
return new VisibilityReport(1, 1);
@@ -795,8 +798,8 @@ public class TaskStackLayoutAlgorithm {
// Quick return when there are no stack tasks
if (mNumStackTasks == 0) {
return new VisibilityReport(Math.max(mNumFreeformTasks, 1),
Math.max(mNumFreeformTasks, 1));
return new VisibilityReport(mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0,
mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0);
}
// Otherwise, walk backwards in the stack and count the number of tasks and visible
@@ -806,8 +809,8 @@ public class TaskStackLayoutAlgorithm {
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_view_header_height);
int numVisibleTasks = Math.max(mNumFreeformTasks, 1);
int numVisibleThumbnails = Math.max(mNumFreeformTasks, 1);
int numVisibleTasks = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 1) : 0;
int numVisibleThumbnails = mNumFreeformTasks > 0 ? Math.max(mNumFreeformTasks, 0) : 0;
float prevScreenY = Integer.MAX_VALUE;
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
@@ -838,15 +841,15 @@ public class TaskStackLayoutAlgorithm {
// Once we hit the next front most task that does not have a visible thumbnail,
// walk through remaining visible set
for (int j = i; j >= 0; j--) {
numVisibleTasks++;
taskProgress = getStackScrollForTask(tasks.get(j));
if (!currentRange.isInRange(taskProgress)) {
continue;
break;
}
numVisibleTasks++;
}
break;
}
} else if (!isFrontMostTaskInGroup) {
} else {
// Affiliated task, no thumbnail
numVisibleTasks++;
}

View File

@@ -868,12 +868,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mTaskViewsClipDirty = false;
}
public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
updateLayoutAlgorithm(boundScrollToNewMinMax, Recents.getConfiguration().getLaunchState());
}
/**
* Updates the layout algorithm min and max virtual scroll bounds.
*/
public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
RecentsActivityLaunchState launchState) {
// Compute the min and max scroll values
mLayoutAlgorithm.update(mStack, mIgnoreTasks);
mLayoutAlgorithm.update(mStack, mIgnoreTasks, launchState);
// Update the freeform workspace background
SystemServicesProxy ssp = Recents.getSystemServices();
@@ -1550,6 +1555,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void onStackTasksUpdated(TaskStack stack) {
if (mAwaitingFirstLayout) {
return;
}
// Update the layout and immediately layout
updateLayoutAlgorithm(false /* boundScroll */);
relayoutTaskViews(AnimationProps.IMMEDIATE);

View File

@@ -16,6 +16,8 @@
package com.android.systemui.recents.views.grid;
import static com.android.systemui.recents.views.TaskStackLayoutAlgorithm.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -26,9 +28,12 @@ import com.android.systemui.R;
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskViewTransform;
import java.util.ArrayList;
public class TaskGridLayoutAlgorithm {
private final String TAG = "TaskGridLayoutAlgorithm";
@@ -313,4 +318,9 @@ public class TaskGridLayoutAlgorithm {
public int getFocusFrameThickness() {
return mFocusedFrameThickness;
}
public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
int visibleCount = Math.min(TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT, tasks.size());
return new VisibilityReport(visibleCount, visibleCount);
}
}

View File

@@ -32,15 +32,10 @@ import java.util.Map.Entry;
*/
class TaskSnapshotCache {
// TODO: Make this more dynamic to accomodate for different clients.
private static final int RETRIEVAL_CACHE_SIZE = 4;
private final WindowManagerService mService;
private final TaskSnapshotLoader mLoader;
private final ArrayMap<AppWindowToken, Integer> mAppTaskMap = new ArrayMap<>();
private final ArrayMap<Integer, CacheEntry> mRunningCache = new ArrayMap<>();
private final LruCache<Integer, TaskSnapshot> mRetrievalCache =
new LruCache<>(RETRIEVAL_CACHE_SIZE);
TaskSnapshotCache(WindowManagerService service, TaskSnapshotLoader loader) {
mService = service;
@@ -55,7 +50,6 @@ class TaskSnapshotCache {
final AppWindowToken top = task.getTopChild();
mAppTaskMap.put(top, task.mTaskId);
mRunningCache.put(task.mTaskId, new CacheEntry(snapshot, task.getTopChild()));
mRetrievalCache.put(task.mTaskId, snapshot);
}
/**
@@ -70,12 +64,6 @@ class TaskSnapshotCache {
if (entry != null) {
return entry.snapshot;
}
// Try the retrieval cache.
final TaskSnapshot snapshot = mRetrievalCache.get(taskId);
if (snapshot != null) {
return snapshot;
}
}
// Try to restore from disk if asked.
@@ -93,13 +81,6 @@ class TaskSnapshotCache {
if (snapshot == null) {
return null;
}
// Only cache non-reduced snapshots.
if (!reducedResolution) {
synchronized (mService.mWindowMap) {
mRetrievalCache.put(taskId, snapshot);
}
}
return snapshot;
}
@@ -111,9 +92,6 @@ class TaskSnapshotCache {
if (taskId != null) {
removeRunningEntry(taskId);
}
if (wtoken.getTask() != null) {
mRetrievalCache.remove(wtoken.getTask().mTaskId);
}
}
/**
@@ -128,7 +106,6 @@ class TaskSnapshotCache {
void onTaskRemoved(int taskId) {
removeRunningEntry(taskId);
mRetrievalCache.remove(taskId);
}
private void removeRunningEntry(int taskId) {
@@ -142,20 +119,12 @@ class TaskSnapshotCache {
void dump(PrintWriter pw, String prefix) {
final String doublePrefix = prefix + " ";
final String triplePrefix = doublePrefix + " ";
final String quadruplePrefix = triplePrefix + " ";
pw.println(prefix + "SnapshotCache");
pw.println(doublePrefix + "RunningCache");
for (int i = mRunningCache.size() - 1; i >= 0; i--) {
final CacheEntry entry = mRunningCache.valueAt(i);
pw.println(triplePrefix + "Entry taskId=" + mRunningCache.keyAt(i));
pw.println(quadruplePrefix + "topApp=" + entry.topApp);
pw.println(quadruplePrefix + "snapshot=" + entry.snapshot);
}
pw.println(doublePrefix + "RetrievalCache");
final Map<Integer, TaskSnapshot> retrievalSnapshot = mRetrievalCache.snapshot();
for (Entry<Integer, TaskSnapshot> entry : retrievalSnapshot.entrySet()) {
pw.println(triplePrefix + "Entry taskId=" + entry.getKey());
pw.println(quadruplePrefix + "snapshot=" + entry.getValue());
pw.println(doublePrefix + "Entry taskId=" + mRunningCache.keyAt(i));
pw.println(triplePrefix + "topApp=" + entry.topApp);
pw.println(triplePrefix + "snapshot=" + entry.snapshot);
}
}

View File

@@ -79,18 +79,6 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
false /* restoreFromDisk */, false /* reducedResolution */));
mCache.onAppDied(window.mAppToken);
// Should still be in the retrieval cache.
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
false /* restoreFromDisk */, false /* reducedResolution */));
// Trash retrieval cache.
for (int i = 0; i < 20; i++) {
mCache.putSnapshot(createWindow(null, FIRST_APPLICATION_WINDOW, "window").getTask(),
createSnapshot());
}
// Should not be in cache anymore
assertNull(mCache.getSnapshot(window.getTask().mTaskId, 0 /* userId */,
false /* restoreFromDisk */, false /* reducedResolution */));
}
@@ -134,9 +122,5 @@ public class TaskSnapshotCacheTest extends TaskSnapshotPersisterTestBase {
// Load it from disk
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, sWm.mCurrentUserId,
true /* restoreFromDisk */, false /* reducedResolution */));
// Make sure it's in the cache now.
assertNotNull(mCache.getSnapshot(window.getTask().mTaskId, sWm.mCurrentUserId,
false /* restoreFromDisk */, false /* reducedResolution */));
}
}