diff options
author | Winson Chung <winsonc@google.com> | 2014-03-14 14:06:29 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2014-03-14 16:53:45 -0700 |
commit | 04dfe0d26b944324ee920001f40d74cff47281d6 (patch) | |
tree | 0c43364c6cf2cf74c45e5006a7405cb24f1b0725 | |
parent | 4d7b092a866d2fce3e11b5a12cda2b87a83af52d (diff) | |
download | frameworks_base-04dfe0d26b944324ee920001f40d74cff47281d6.zip frameworks_base-04dfe0d26b944324ee920001f40d74cff47281d6.tar.gz frameworks_base-04dfe0d26b944324ee920001f40d74cff47281d6.tar.bz2 |
Simplifying memory management, use Task Keys as resource cache keys.
- Attempts to load non-topmost task thumbnails from cache
- Ensuring that we release all references to the activity from the bg loader
- Removes background loading debug flag
- Moving callbacks into their respective classes
- cleaning up some callbacks when data is loaded in the bg
Change-Id: Ibb968349d08084922d5b28e432b76a165bf20d6b
14 files changed, 243 insertions, 325 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index 57ebbc2..34dd726 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -28,10 +28,10 @@ public class Constants { public static class App { public static final boolean EnableTaskFiltering = false; public static final boolean EnableTaskStackClipping = false; - public static final boolean EnableBackgroundTaskLoading = true; - public static final boolean ForceDisableBackgroundCache = false; + // This disables the bitmap and icon caches to + public static final boolean DisableBackgroundCache = false; - public static final boolean TaskDataLoader = false; + public static final boolean TaskDataLoader = true; public static final boolean SystemUIHandshake = false; public static final boolean TimeSystemCalls = false; public static final boolean Memory = false; @@ -43,7 +43,7 @@ public class Constants { public static final boolean TouchEvents = false; public static final boolean MeasureAndLayout = false; public static final boolean Clipping = false; - public static final boolean HwLayers = false; + public static final boolean HwLayers = true; } public static class TaskStack { @@ -74,8 +74,6 @@ public class Constants { public static class Animation { public static final int TaskRemovedReshuffleDuration = 200; public static final int SnapScrollBackDuration = 650; - public static final int SwipeDismissDuration = 350; - public static final int SwipeSnapBackDuration = 350; } // The padding will be applied to the smallest dimension, and then applied to all sides diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index fc4d819..e3908ff 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -45,7 +45,6 @@ public class RecentsActivity extends Activity { SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount); ArrayList<TaskStack> stacks = root.getStacks(); if (!stacks.isEmpty()) { - // XXX: We just replace the root every time for now, we will change this in the future mRecentsView.setBSP(root); } @@ -155,7 +154,7 @@ public class RecentsActivity extends Activity { Console.AnsiRed); super.onPause(); - // Stop the loader when we leave Recents + // Stop the loader immediately when we leave Recents RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); loader.stopLoader(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java index 96efed4..c8576b2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java @@ -36,7 +36,6 @@ import com.android.systemui.recents.model.TaskStack; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.concurrent.ConcurrentLinkedQueue; @@ -84,7 +83,9 @@ class TaskResourceLoader implements Runnable { TaskResourceLoadQueue mLoadQueue; DrawableLruCache mIconCache; BitmapLruCache mThumbnailCache; + boolean mCancelled; + boolean mWaitingOnLoadQueue; /** Constructor, creates a new loading thread that loads task resources in the background */ public TaskResourceLoader(TaskResourceLoadQueue loadQueue, DrawableLruCache iconCache, @@ -116,6 +117,11 @@ class TaskResourceLoader implements Runnable { Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|stop]"); // Mark as cancelled for the thread to pick up mCancelled = true; + // If we are waiting for the load queue for more tasks, then we can just reset the + // Context now, since nothing is using it + if (mWaitingOnLoadQueue) { + mContext = null; + } } @Override @@ -124,6 +130,8 @@ class TaskResourceLoader implements Runnable { Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|run|" + Thread.currentThread().getId() + "]"); if (mCancelled) { + Console.log(Constants.DebugFlags.App.TaskDataLoader, + "[TaskResourceLoader|cancel|" + Thread.currentThread().getId() + "]"); // We have to unset the context here, since the background thread may be using it // when we call stop() mContext = null; @@ -142,50 +150,52 @@ class TaskResourceLoader implements Runnable { final Task t = mLoadQueue.nextTask(); if (t != null) { try { - Drawable cachedIcon = mIconCache.get(t); - Bitmap cachedThumbnail = mThumbnailCache.get(t); + Drawable loadIcon = mIconCache.get(t.key); + Bitmap loadThumbnail = mThumbnailCache.get(t.key); Console.log(Constants.DebugFlags.App.TaskDataLoader, " [TaskResourceLoader|load]", - t + " icon: " + cachedIcon + " thumbnail: " + cachedThumbnail); + t + " icon: " + loadIcon + " thumbnail: " + loadThumbnail); // Load the icon - if (cachedIcon == null) { + if (loadIcon == null) { PackageManager pm = mContext.getPackageManager(); - ActivityInfo info = pm.getActivityInfo(t.intent.getComponent(), + ActivityInfo info = pm.getActivityInfo(t.key.intent.getComponent(), PackageManager.GET_META_DATA); Drawable icon = info.loadIcon(pm); if (!mCancelled) { Console.log(Constants.DebugFlags.App.TaskDataLoader, " [TaskResourceLoader|loadIcon]", icon); - t.icon = icon; - mIconCache.put(t, icon); + loadIcon = icon; + mIconCache.put(t.key, icon); } } // Load the thumbnail - if (cachedThumbnail == null) { + if (loadThumbnail == null) { ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - Bitmap thumbnail = am.getTaskTopThumbnail(t.id); + Bitmap thumbnail = am.getTaskTopThumbnail(t.key.id); if (!mCancelled) { if (thumbnail != null) { Console.log(Constants.DebugFlags.App.TaskDataLoader, " [TaskResourceLoader|loadThumbnail]", thumbnail); - t.thumbnail = thumbnail; - mThumbnailCache.put(t, thumbnail); + loadThumbnail = thumbnail; + mThumbnailCache.put(t.key, thumbnail); } else { Console.logError(mContext, "Failed to load task top thumbnail for: " + - t.intent.getComponent().getPackageName()); + t.key.intent.getComponent().getPackageName()); } } } if (!mCancelled) { // Notify that the task data has changed + final Drawable newIcon = loadIcon; + final Bitmap newThumbnail = loadThumbnail; mMainThreadHandler.post(new Runnable() { @Override public void run() { - t.notifyTaskDataChanged(); + t.notifyTaskDataLoaded(newThumbnail, newIcon); } }); } @@ -200,7 +210,9 @@ class TaskResourceLoader implements Runnable { try { Console.log(Constants.DebugFlags.App.TaskDataLoader, "[TaskResourceLoader|waitOnLoadQueue]"); + mWaitingOnLoadQueue = true; mLoadQueue.wait(); + mWaitingOnLoadQueue = false; } catch (InterruptedException ie) { ie.printStackTrace(); } @@ -211,14 +223,17 @@ class TaskResourceLoader implements Runnable { } } -/** The drawable cache */ -class DrawableLruCache extends LruCache<Task, Drawable> { +/** + * The drawable cache. By using the Task's key, we can prevent holding onto a reference to the Task + * resource data, while keeping the cache data in memory where necessary. + */ +class DrawableLruCache extends LruCache<Task.TaskKey, Drawable> { public DrawableLruCache(int cacheSize) { super(cacheSize); } @Override - protected int sizeOf(Task t, Drawable d) { + protected int sizeOf(Task.TaskKey t, Drawable d) { // The cache size will be measured in kilobytes rather than number of items // NOTE: this isn't actually correct, as the icon may be smaller int maxBytes = (d.getIntrinsicWidth() * d.getIntrinsicHeight() * 4); @@ -226,14 +241,17 @@ class DrawableLruCache extends LruCache<Task, Drawable> { } } -/** The bitmap cache */ -class BitmapLruCache extends LruCache<Task, Bitmap> { +/** + * The bitmap cache. By using the Task's key, we can prevent holding onto a reference to the Task + * resource data, while keeping the cache data in memory where necessary. + */ +class BitmapLruCache extends LruCache<Task.TaskKey, Bitmap> { public BitmapLruCache(int cacheSize) { super(cacheSize); } @Override - protected int sizeOf(Task t, Bitmap bitmap) { + protected int sizeOf(Task.TaskKey t, Bitmap bitmap) { // The cache size will be measured in kilobytes rather than number of items return bitmap.getAllocationByteCount() / 1024; } @@ -257,16 +275,18 @@ public class RecentsTaskLoader { /** Private Constructor */ private RecentsTaskLoader(Context context) { - // Calculate the cache sizes + // Calculate the cache sizes, we just use a reasonable number here similar to those + // suggested in the Android docs, 1/8th for the thumbnail cache and 1/32 of the max memory + // for icons. int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); mMaxThumbnailCacheSize = maxMemory / 8; mMaxIconCacheSize = mMaxThumbnailCacheSize / 4; - int iconCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : + int iconCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 : mMaxIconCacheSize; - int thumbnailCacheSize = Constants.DebugFlags.App.ForceDisableBackgroundCache ? 1 : + int thumbnailCacheSize = Constants.DebugFlags.App.DisableBackgroundCache ? 1 : mMaxThumbnailCacheSize; - Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading, + Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|init]", "thumbnailCache: " + thumbnailCacheSize + " iconCache: " + iconCacheSize); @@ -351,36 +371,34 @@ public class RecentsTaskLoader { ActivityInfo info = pm.getActivityInfo(t.baseIntent.getComponent(), PackageManager.GET_META_DATA); String title = info.loadLabel(pm).toString(); - Task task; + boolean isForemostTask = (i == (taskCount - 1)); + // Preload the specified number of apps - if (i >= (taskCount - preloadCount) || - !Constants.DebugFlags.App.EnableBackgroundTaskLoading) { + if (i >= (taskCount - preloadCount)) { Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|preloadTask]", "i: " + i + " task: " + t.baseIntent.getComponent().getPackageName()); - task = new Task(t.persistentId, t.baseIntent, title, null, null); + Task task = new Task(t.persistentId, t.baseIntent, title); - // Load the icon (if possible from the cache) - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - task.icon = mIconCache.get(task); + // Load the icon (if possible and not the foremost task, from the cache) + if (!isForemostTask) { + task.icon = mIconCache.get(task.key); } if (task.icon == null) { task.icon = info.loadIcon(pm); - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - mIconCache.put(task, task.icon); - } + mIconCache.put(task.key, task.icon); } - // Load the thumbnail (if possible from the cache) - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - task.thumbnail = mThumbnailCache.get(task); + // Load the thumbnail (if possible and not the foremost task, from the cache) + if (!isForemostTask) { + task.thumbnail = mThumbnailCache.get(task.key); } if (task.thumbnail == null) { + Console.log(Constants.DebugFlags.App.TaskDataLoader, + "[RecentsTaskLoader|loadingTaskThumbnail]"); task.thumbnail = am.getTaskTopThumbnail(t.id); - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - mThumbnailCache.put(task, task.thumbnail); - } + mThumbnailCache.put(task.key, task.thumbnail); } // Create as many tasks a we want to multiply by @@ -394,19 +412,9 @@ public class RecentsTaskLoader { for (int j = 0; j < Constants.Values.RecentsTaskLoader.TaskEntryMultiplier; j++) { Console.log(Constants.DebugFlags.App.TaskDataLoader, " [RecentsTaskLoader|task]", t.baseIntent.getComponent().getPackageName()); - task = new Task(t.persistentId, t.baseIntent, title, null, null); - stack.addTask(task); + stack.addTask(new Task(t.persistentId, t.baseIntent, title)); } } - - /* - if (stacks.containsKey(t.stackId)) { - builder = stacks.get(t.stackId); - } else { - builder = new TaskStackBuilder(); - stacks.put(t.stackId, builder); - } - */ } Console.log(Constants.DebugFlags.App.TimeSystemCalls, "[RecentsTaskLoader|getAllTaskTopThumbnail]", @@ -428,64 +436,59 @@ public class RecentsTaskLoader { } catch (Exception e) { e.printStackTrace(); } + + // Start the task loader mLoader.start(context); + return root; } /** Acquires the task resource data from the pool. */ public void loadTaskData(Task t) { - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - Drawable icon = mIconCache.get(t); - Bitmap thumbnail = mThumbnailCache.get(t); - - Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]", - t + " icon: " + icon + " thumbnail: " + thumbnail + - " thumbnailCacheSize: " + mThumbnailCache.size()); - - boolean requiresLoad = false; - if (icon == null) { - icon = mDefaultIcon; - requiresLoad = true; - } - if (thumbnail == null) { - thumbnail = mDefaultThumbnail; - requiresLoad = true; - } - if (requiresLoad) { - mLoadQueue.addTask(t); - } - t.notifyTaskLoaded(thumbnail, icon); + Drawable icon = mIconCache.get(t.key); + Bitmap thumbnail = mThumbnailCache.get(t.key); + + Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|loadTask]", + t + " icon: " + icon + " thumbnail: " + thumbnail + + " thumbnailCacheSize: " + mThumbnailCache.size()); + + boolean requiresLoad = false; + if (icon == null) { + icon = mDefaultIcon; + requiresLoad = true; + } + if (thumbnail == null) { + thumbnail = mDefaultThumbnail; + requiresLoad = true; } + if (requiresLoad) { + mLoadQueue.addTask(t); + } + t.notifyTaskDataLoaded(thumbnail, icon); } /** Releases the task resource data back into the pool. */ public void unloadTaskData(Task t) { - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - Console.log(Constants.DebugFlags.App.TaskDataLoader, - "[RecentsTaskLoader|unloadTask]", t + - " thumbnailCacheSize: " + mThumbnailCache.size()); - mLoadQueue.removeTask(t); - t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon); - } else { - t.notifyTaskUnloaded(null, null); - } + Console.log(Constants.DebugFlags.App.TaskDataLoader, + "[RecentsTaskLoader|unloadTask]", t + + " thumbnailCacheSize: " + mThumbnailCache.size()); + + mLoadQueue.removeTask(t); + t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon); } /** Completely removes the resource data from the pool. */ public void deleteTaskData(Task t) { - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - Console.log(Constants.DebugFlags.App.TaskDataLoader, - "[RecentsTaskLoader|deleteTask]", t); - mLoadQueue.removeTask(t); - mThumbnailCache.remove(t); - mIconCache.remove(t); - t.notifyTaskUnloaded(mDefaultThumbnail, mDefaultIcon); - } else { - t.notifyTaskUnloaded(null, null); - } + Console.log(Constants.DebugFlags.App.TaskDataLoader, + "[RecentsTaskLoader|deleteTask]", t); + + mLoadQueue.removeTask(t); + mThumbnailCache.remove(t.key); + mIconCache.remove(t.key); + t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultIcon); } - /** Stops the task loader */ + /** Stops the task loader and clears all pending tasks */ void stopLoader() { Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|stopLoader]"); mLoader.stop(); @@ -496,46 +499,30 @@ public class RecentsTaskLoader { Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|onTrimMemory]", Console.trimMemoryLevelToString(level)); - if (Constants.DebugFlags.App.EnableBackgroundTaskLoading) { - // If we are hidden, then we should unload each of the task keys - if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { - Console.log(Constants.DebugFlags.App.Memory, "[RecentsTaskLoader|unloadTasks]" - ); - // Unload each of the keys in the thumbnail cache - Map<Task, Bitmap> thumbnailCache = mThumbnailCache.snapshot(); - for (Task t : thumbnailCache.keySet()) { - unloadTaskData(t); - } - // As well as the keys in the icon cache - Map<Task, Drawable> iconCache = mIconCache.snapshot(); - for (Task t : iconCache.keySet()) { - unloadTaskData(t); - } - } - - switch (level) { - case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: - case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: - // We are leaving recents, so trim the data a bit - mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2); - mIconCache.trimToSize(mMaxIconCacheSize / 2); - break; - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: - case ComponentCallbacks2.TRIM_MEMORY_MODERATE: - // We are going to be low on memory - mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4); - mIconCache.trimToSize(mMaxIconCacheSize / 4); - break; - case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: - case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: - // We are low on memory, so release everything - mThumbnailCache.evictAll(); - mIconCache.evictAll(); - break; - default: - break; - } + switch (level) { + case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: + // Do nothing + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: + case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: + // We are leaving recents, so trim the data a bit + mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 2); + mIconCache.trimToSize(mMaxIconCacheSize / 2); + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: + case ComponentCallbacks2.TRIM_MEMORY_MODERATE: + // We are going to be low on memory + mThumbnailCache.trimToSize(mMaxThumbnailCacheSize / 4); + mIconCache.trimToSize(mMaxIconCacheSize / 4); + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: + case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: + // We are low on memory, so release everything + mThumbnailCache.evictAll(); + mIconCache.evictAll(); + break; + default: + break; } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java index 5893abc..1dd1be6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java @@ -17,6 +17,7 @@ package com.android.systemui.recents.model; import android.content.Context; +import android.graphics.Rect; import java.util.ArrayList; @@ -26,6 +27,14 @@ import java.util.ArrayList; * stacks should be placed. */ public class SpaceNode { + /* BSP node callbacks */ + public interface SpaceNodeCallbacks { + /** Notifies when a node is added */ + public void onSpaceNodeAdded(SpaceNode node); + /** Notifies when a node is measured */ + public void onSpaceNodeMeasured(SpaceNode node, Rect rect); + } + Context mContext; SpaceNode mStartNode; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNodeCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNodeCallbacks.java deleted file mode 100644 index 31b02e7..0000000 --- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNodeCallbacks.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2014 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.graphics.Rect; - - -/* BSP node callbacks */ -public interface SpaceNodeCallbacks { - /** Notifies when a node is added */ - public void onSpaceNodeAdded(SpaceNode node); - /** Notifies when a node is measured */ - public void onSpaceNodeMeasured(SpaceNode node, Rect rect); -}
\ No newline at end of file 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 378984c..0c3c528 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java @@ -26,17 +26,53 @@ import com.android.systemui.recents.Constants; * A task represents the top most task in the system's task stack. */ public class Task { - public final int id; - public final Intent intent; + /* Task callbacks */ + public interface TaskCallbacks { + /* Notifies when a task has been bound */ + public void onTaskDataLoaded(); + /* Notifies when a task has been unbound */ + public void onTaskDataUnloaded(); + } + + /* The Task Key represents the unique primary key for the task */ + public static class TaskKey { + public final int id; + public final Intent intent; + + public TaskKey(int id, Intent intent) { + this.id = id; + this.intent = intent; + } + + @Override + public boolean equals(Object o) { + return hashCode() == o.hashCode(); + } + + @Override + public int hashCode() { + return id; + } + + @Override + public String toString() { + return "Task.Key: " + id + ", " + intent.getComponent().getPackageName(); + } + } + + public TaskKey key; public String title; public Drawable icon; public Bitmap thumbnail; TaskCallbacks mCb; + public Task(int id, Intent intent, String activityTitle) { + this(id, intent, activityTitle, null, null); + } + public Task(int id, Intent intent, String activityTitle, Drawable icon, Bitmap thumbnail) { - this.id = id; - this.intent = intent; + this.key = new TaskKey(id, intent); this.title = activityTitle; this.icon = icon; this.thumbnail = thumbnail; @@ -47,28 +83,21 @@ public class Task { mCb = cb; } - /** Notifies the callback listeners that this task's data has changed */ - public void notifyTaskDataChanged() { - if (mCb != null) { - mCb.onTaskDataChanged(this); - } - } - /** Notifies the callback listeners that this task has been loaded */ - public void notifyTaskLoaded(Bitmap thumbnail, Drawable icon) { + public void notifyTaskDataLoaded(Bitmap thumbnail, Drawable icon) { this.icon = icon; this.thumbnail = thumbnail; if (mCb != null) { - mCb.onTaskBound(); + mCb.onTaskDataLoaded(); } } /** Notifies the callback listeners that this task has been unloaded */ - public void notifyTaskUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) { + public void notifyTaskDataUnloaded(Bitmap defaultThumbnail, Drawable defaultIcon) { icon = defaultIcon; thumbnail = defaultThumbnail; if (mCb != null) { - mCb.onTaskUnbound(); + mCb.onTaskDataUnloaded(); } } @@ -83,12 +112,11 @@ public class Task { // Otherwise, check that the id and intent match (the other fields can be asynchronously // loaded and is unsuitable to testing the identity of this Task) Task t = (Task) o; - return (id == t.id) && - (intent.equals(t.intent)); + return key.equals(t.key); } @Override public String toString() { - return "Task: " + intent.getComponent().getPackageName() + " [" + super.toString() + "]"; + return "Task: " + key.intent.getComponent().getPackageName() + " [" + super.toString() + "]"; } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java deleted file mode 100644 index 712580d..0000000 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskCallbacks.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2014 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; - -/* Task callbacks */ -public interface TaskCallbacks { - /* Notifies when a task's data has been updated */ - public void onTaskDataChanged(Task task); - /* Notifies when a task has been bound */ - public void onTaskBound(); - /* Notifies when a task has been unbound */ - public void onTaskUnbound(); -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index a5aa387..f2f89ae 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -119,6 +119,18 @@ class FilteredTaskList { * The task stack contains a list of multiple tasks. */ public class TaskStack { + /* Task stack callbacks */ + public interface TaskStackCallbacks { + /* Notifies when a task has been added to the stack */ + public void onStackTaskAdded(TaskStack stack, Task t); + /* Notifies when a task has been removed from the stack */ + public void onStackTaskRemoved(TaskStack stack, Task t); + /** Notifies when the stack was filtered */ + public void onStackFiltered(TaskStack stack); + /** Notifies when the stack was un-filtered */ + public void onStackUnfiltered(TaskStack stack); + } + Context mContext; FilteredTaskList mTaskList = new FilteredTaskList(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStackCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStackCallbacks.java deleted file mode 100644 index 4bec655..0000000 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStackCallbacks.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2014 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; - -/* Task stack callbacks */ -public interface TaskStackCallbacks { - /* Notifies when a task has been added to the stack */ - public void onStackTaskAdded(TaskStack stack, Task t); - /* Notifies when a task has been removed from the stack */ - public void onStackTaskRemoved(TaskStack stack, Task t); - /** Notifies when the stack was filtered */ - public void onStackFiltered(TaskStack stack); - /** Notifies when the stack was un-filtered */ - public void onStackUnfiltered(TaskStack stack); -}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index c92041c..32110cf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -39,7 +39,7 @@ import java.util.ArrayList; * This view is the the top level layout that contains TaskStacks (which are laid out according * to their SpaceNode bounds. */ -public class RecentsView extends FrameLayout implements TaskStackViewCallbacks { +public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks { // The space partitioning root of this container SpaceNode mBSP; @@ -52,8 +52,7 @@ public class RecentsView extends FrameLayout implements TaskStackViewCallbacks { public void setBSP(SpaceNode n) { mBSP = n; - // XXX: We shouldn't be recereating new stacks every time, but for now, that is OK - // Add all the stacks for this partition + // Create and add all the stacks for this partition of space. removeAllViews(); ArrayList<TaskStack> stacks = mBSP.getStacks(); for (TaskStack stack : stacks) { @@ -206,7 +205,7 @@ public class RecentsView extends FrameLayout implements TaskStackViewCallbacks { } // Launch the activity with the desired animation - Intent i = new Intent(task.intent); + Intent i = new Intent(task.key.intent); i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY | Intent.FLAG_ACTIVITY_TASK_ON_HOME | Intent.FLAG_ACTIVITY_NEW_TASK); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 7753d69..a3ed535 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -33,7 +33,6 @@ import android.view.ViewConfiguration; import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.OverScroller; -import android.widget.Toast; import com.android.systemui.recents.Console; import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; @@ -41,18 +40,20 @@ import com.android.systemui.recents.RecentsTaskLoader; import com.android.systemui.recents.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; -import com.android.systemui.recents.model.TaskStackCallbacks; import java.util.ArrayList; -/** The TaskView callbacks */ -interface TaskStackViewCallbacks { - public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t); -} /* The visual representation of a task stack view */ -public class TaskStackView extends FrameLayout implements TaskStackCallbacks, TaskViewCallbacks, - ViewPoolConsumer<TaskView, Task>, View.OnClickListener { +public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks, + TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>, + View.OnClickListener { + + /** The TaskView callbacks */ + interface TaskStackViewCallbacks { + public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t); + } + TaskStack mStack; TaskStackViewTouchHandler mTouchHandler; TaskStackViewCallbacks mCb; @@ -348,7 +349,8 @@ public class TaskStackView extends FrameLayout implements TaskStackCallbacks, Ta tv.disableHwLayers(); } } else if (mHwLayersRefCount < 0) { - throw new RuntimeException("Invalid hw layers ref count"); + new Throwable("Invalid hw layers ref count").printStackTrace(); + Console.logError(getContext(), "Invalid HW layers ref count"); } } @@ -598,7 +600,7 @@ public class TaskStackView extends FrameLayout implements TaskStackCallbacks, Ta // Setup and attach the view to the window Task task = prepareData; // We try and rebind the task (this MUST be done before the task filled) - tv.bindToTask(task, this); + tv.onTaskBound(task); // Request that this tasks's data be filled RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); loader.loadTaskData(task); @@ -619,7 +621,10 @@ public class TaskStackView extends FrameLayout implements TaskStackCallbacks, Ta "" + insertIndex); if (isNewView) { addView(tv, insertIndex); + + // Set the callbacks and listeners for this new view tv.setOnClickListener(this); + tv.setCallbacks(this); } else { attachViewToParent(tv, insertIndex, tv.getLayoutParams()); } @@ -649,7 +654,7 @@ public class TaskStackView extends FrameLayout implements TaskStackCallbacks, Ta mStack.filterTasks(tv.getTask()); } } else { - Toast.makeText(getContext(), "Task Filtering TBD", Toast.LENGTH_SHORT).show(); + Console.logError(getContext(), "Task Filtering TBD"); } } @@ -995,7 +1000,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback { final ActivityManager am = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE); if (am != null) { - am.removeTask(tv.getTask().id, + am.removeTask(tv.getTask().key.id, ActivityManager.REMOVE_TASK_KILL_PROCESS); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 9ef74ca..ace2428 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -39,13 +39,7 @@ import com.android.systemui.recents.Console; import com.android.systemui.recents.Constants; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.model.Task; -import com.android.systemui.recents.model.TaskCallbacks; -/** The TaskView callbacks */ -interface TaskViewCallbacks { - public void onTaskIconClicked(TaskView tv); - // public void onTaskViewReboundToTask(TaskView tv, Task t); -} /** The task thumbnail view */ class TaskThumbnailView extends ImageView { @@ -66,7 +60,7 @@ class TaskThumbnailView extends ImageView { // Update the bar color if (Constants.Values.TaskView.DrawColoredTaskBars) { int[] colors = {0xFFCC0C39, 0xFFE6781E, 0xFFC8CF02, 0xFF1693A7}; - mBarColor = colors[mTask.intent.getComponent().getPackageName().length() % colors.length]; + mBarColor = colors[mTask.key.intent.getComponent().getPackageName().length() % colors.length]; } setImageBitmap(t.thumbnail); @@ -213,7 +207,13 @@ class TaskIconView extends ImageView { } /* A task view */ -public class TaskView extends FrameLayout implements View.OnClickListener, TaskCallbacks { +public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks { + /** The TaskView callbacks */ + interface TaskViewCallbacks { + public void onTaskIconClicked(TaskView tv); + // public void onTaskViewReboundToTask(TaskView tv, Task t); + } + Task mTask; TaskThumbnailView mThumbnailView; TaskIconView mIconView; @@ -247,26 +247,11 @@ public class TaskView extends FrameLayout implements View.OnClickListener, TaskC ((LayoutParams) mIconView.getLayoutParams()).rightMargin = offset; } - /** Set the task and callback */ - void bindToTask(Task t, TaskViewCallbacks cb) { - mTask = t; - mTask.setCallbacks(this); + /** Set callback */ + void setCallbacks(TaskViewCallbacks cb) { mCb = cb; } - /** Actually synchronizes the model data into the views */ - private void syncToTask() { - mThumbnailView.rebindToTask(mTask, false); - mIconView.rebindToTask(mTask, false); - } - - /** Unset the task and callback */ - private void unbindFromTask() { - mTask.setCallbacks(null); - mThumbnailView.unbindFromTask(); - mIconView.unbindFromTask(); - } - /** Gets the task */ Task getTask() { return mTask; @@ -367,26 +352,25 @@ public class TaskView extends FrameLayout implements View.OnClickListener, TaskC /**** TaskCallbacks Implementation ****/ - @Override - public void onTaskDataChanged(Task task) { - Console.log(Constants.DebugFlags.App.EnableBackgroundTaskLoading, - "[TaskView|onTaskDataChanged]", task); - - // Only update this task view if the changed task is the same as the task for this view - if (mTask == task) { - mThumbnailView.rebindToTask(mTask, true); - mIconView.rebindToTask(mTask, true); - } + /** Binds this task view to the task */ + public void onTaskBound(Task t) { + mTask = t; + mTask.setCallbacks(this); } @Override - public void onTaskBound() { - syncToTask(); + public void onTaskDataLoaded() { + // Bind each of the views to the new task data + mThumbnailView.rebindToTask(mTask, false); + mIconView.rebindToTask(mTask, false); } @Override - public void onTaskUnbound() { - unbindFromTask(); + public void onTaskDataUnloaded() { + // Unbind each of the views from the task data and remove the task callback + mTask.setCallbacks(null); + mThumbnailView.unbindFromTask(); + mIconView.unbindFromTask(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java index f7d7095..af0094e 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java @@ -24,6 +24,15 @@ import java.util.LinkedList; /* A view pool to manage more views than we can visibly handle */ public class ViewPool<V, T> { + + /* An interface to the consumer of a view pool */ + public interface ViewPoolConsumer<V, T> { + public V createView(Context context); + public void prepareViewToEnterPool(V v); + public void prepareViewToLeavePool(V v, T prepareData, boolean isNewView); + public boolean hasPreferredData(V v, T preferredData); + } + Context mContext; ViewPoolConsumer<V, T> mViewCreator; LinkedList<V> mPool = new LinkedList<V>(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPoolConsumer.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPoolConsumer.java deleted file mode 100644 index 50f45bf..0000000 --- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPoolConsumer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2014 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.views; - -import android.content.Context; - - -/* An interface to the consumer of a view pool */ -public interface ViewPoolConsumer<V, T> { - public V createView(Context context); - public void prepareViewToEnterPool(V v); - public void prepareViewToLeavePool(V v, T prepareData, boolean isNewView); - public boolean hasPreferredData(V v, T preferredData); -} |