Loading packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java +5 −37 Original line number Diff line number Diff line Loading @@ -17,15 +17,12 @@ package com.android.systemui.shared.recents.model; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; /** * Background task resource loader Loading @@ -40,8 +37,7 @@ class BackgroundTaskLoader implements Runnable { private final Handler mMainThreadHandler; private final TaskResourceLoadQueue mLoadQueue; private final TaskKeyLruCache<Drawable> mIconCache; private final BitmapDrawable mDefaultIcon; private final IconLoader mIconLoader; private boolean mStarted; private boolean mCancelled; Loading @@ -51,11 +47,9 @@ class BackgroundTaskLoader implements Runnable { /** Constructor, creates a new loading thread that loads task resources in the background */ public BackgroundTaskLoader(TaskResourceLoadQueue loadQueue, TaskKeyLruCache<Drawable> iconCache, BitmapDrawable defaultIcon, OnIdleChangedListener onIdleChangedListener) { IconLoader iconLoader, OnIdleChangedListener onIdleChangedListener) { mLoadQueue = loadQueue; mIconCache = iconCache; mDefaultIcon = defaultIcon; mIconLoader = iconLoader; mMainThreadHandler = new Handler(); mOnIdleChangedListener = onIdleChangedListener; mLoadThread = new HandlerThread("Recents-TaskResourceLoader", Loading Loading @@ -140,32 +134,7 @@ class BackgroundTaskLoader implements Runnable { // Load the next item from the queue final Task t = mLoadQueue.nextTask(); if (t != null) { Drawable cachedIcon = mIconCache.get(t.key); // Load the icon if it is stale or we haven't cached one yet if (cachedIcon == null) { cachedIcon = ActivityManagerWrapper.getInstance().getBadgedTaskDescriptionIcon( mContext, t.taskDescription, t.key.userId, mContext.getResources()); if (cachedIcon == null) { ActivityInfo info = PackageManagerWrapper.getInstance().getActivityInfo( t.key.getComponent(), t.key.userId); if (info != null) { if (DEBUG) Log.d(TAG, "Loading icon: " + t.key); cachedIcon = ActivityManagerWrapper.getInstance().getBadgedActivityIcon( info, t.key.userId); } } if (cachedIcon == null) { cachedIcon = mDefaultIcon; } // At this point, even if we can't load the icon, we will set the // default icon. mIconCache.put(t.key, cachedIcon); } final Drawable icon = mIconLoader.getIcon(t); if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key); final ThumbnailData thumbnailData = ActivityManagerWrapper.getInstance().getTaskThumbnail(t.key.id, Loading @@ -173,9 +142,8 @@ class BackgroundTaskLoader implements Runnable { if (!mCancelled) { // Notify that the task data has changed final Drawable finalIcon = cachedIcon; mMainThreadHandler.post( () -> t.notifyTaskDataLoaded(thumbnailData, finalIcon)); () -> t.notifyTaskDataLoaded(thumbnailData, icon)); } } } Loading packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java 0 → 100644 +183 −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.shared.recents.model; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.util.IconDrawableFactory; import android.util.Log; import android.util.LruCache; import com.android.systemui.shared.system.PackageManagerWrapper; public abstract class IconLoader { private static final String TAG = "IconLoader"; protected final Context mContext; protected final TaskKeyLruCache<Drawable> mIconCache; protected final LruCache<ComponentName, ActivityInfo> mActivityInfoCache; public IconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { mContext = context; mIconCache = iconCache; mActivityInfoCache = activityInfoCache; } /** * Returns the activity info for the given task key, retrieving one from the system if the * task key is expired. * * TODO: Move this to an ActivityInfoCache class */ public ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) { ComponentName cn = taskKey.getComponent(); ActivityInfo activityInfo = mActivityInfoCache.get(cn); if (activityInfo == null) { activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, taskKey.userId); if (cn == null || activityInfo == null) { Log.e(TAG, "Unexpected null component name or activity info: " + cn + ", " + activityInfo); return null; } mActivityInfoCache.put(cn, activityInfo); } return activityInfo; } public Drawable getIcon(Task t) { Drawable cachedIcon = mIconCache.get(t.key); if (cachedIcon == null) { cachedIcon = createNewIconForTask(t.key, t.taskDescription, true /* returnDefault */); mIconCache.put(t.key, cachedIcon); } return cachedIcon; } /** * Returns the cached task icon if the task key is not expired, updating the cache if it is. */ public Drawable getAndInvalidateIfModified(Task.TaskKey taskKey, ActivityManager.TaskDescription td, boolean loadIfNotCached) { // Return the cached activity icon if it exists Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey); if (icon != null) { return icon; } if (loadIfNotCached) { icon = createNewIconForTask(taskKey, td, false /* returnDefault */); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } } // We couldn't load any icon return null; } private Drawable createNewIconForTask(Task.TaskKey taskKey, ActivityManager.TaskDescription desc, boolean returnDefault) { int userId = taskKey.userId; Bitmap tdIcon = desc.getInMemoryIcon(); if (tdIcon != null) { return createDrawableFromBitmap(tdIcon, userId); } if (desc.getIconResource() != 0) { // TODO: Use task context here try { return createBadgedDrawable(mContext.getDrawable(desc.getIconResource()), userId); } catch (Resources.NotFoundException e) { Log.e(TAG, "Could not find icon drawable from resource", e); } } tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon( desc.getIconFilename(), userId); if (tdIcon != null) { return createDrawableFromBitmap(tdIcon, userId); } // Load the icon from the activity info and cache it ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey); if (activityInfo != null) { Drawable icon = getBadgedActivityIcon(activityInfo, userId); if (icon != null) { return icon; } } // At this point, even if we can't load the icon, we will set the default icon. return returnDefault ? getDefaultIcon(userId) : null; } public abstract Drawable getDefaultIcon(int userId); protected Drawable createDrawableFromBitmap(Bitmap icon, int userId) { return createBadgedDrawable(new BitmapDrawable(mContext.getResources(), icon), userId); } protected abstract Drawable createBadgedDrawable(Drawable icon, int userId); /** * @return the activity icon for the ActivityInfo for a user, badging if necessary. */ protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId); public static class DefaultIconLoader extends IconLoader { private final BitmapDrawable mDefaultIcon; private final IconDrawableFactory mDrawableFactory; public DefaultIconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { super(context, iconCache, activityInfoCache); // Create the default assets Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); icon.eraseColor(0); mDefaultIcon = new BitmapDrawable(context.getResources(), icon); mDrawableFactory = IconDrawableFactory.newInstance(context); } @Override public Drawable getDefaultIcon(int userId) { return mDefaultIcon; } @Override protected Drawable createBadgedDrawable(Drawable icon, int userId) { if (userId != UserHandle.myUserId()) { icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(userId)); } return icon; } @Override protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId) { return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId); } } } packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java +2 −2 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ public class RecentsTaskLoadPlan { ? loader.getAndUpdateContentDescription(taskKey, t.taskDescription) : ""; Drawable icon = isStackTask ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false) ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, false) : null; ThumbnailData thumbnail = loader.getAndUpdateThumbnail(taskKey, false /* loadIfNotCached */, false /* storeInCache */); Loading Loading @@ -179,7 +179,7 @@ public class RecentsTaskLoadPlan { if (opts.loadIcons && (isRunningTask || isVisibleTask)) { if (task.icon == null) { task.icon = loader.getAndUpdateActivityIcon(taskKey, task.taskDescription, res, task.icon = loader.getAndUpdateActivityIcon(taskKey, task.taskDescription, true); } } Loading packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java +15 −58 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Looper; import android.os.Trace; Loading @@ -36,7 +33,6 @@ import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.PreloadOpti import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.TaskKeyLruCache.EvictionCallback; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import java.io.PrintWriter; import java.util.Map; Loading @@ -61,8 +57,6 @@ public class RecentsTaskLoader { // Disable all thumbnail loading. public static final int SVELTE_DISABLE_LOADING = 3; private final Context mContext; // This activity info LruCache is useful because it can be expensive to retrieve ActivityInfos // for many tasks, which we use to get the activity labels and icons. Unlike the other caches // below, this is per-package so we can't invalidate the items in the cache based on the last Loading @@ -73,6 +67,7 @@ public class RecentsTaskLoader { private final TaskKeyLruCache<String> mActivityLabelCache; private final TaskKeyLruCache<String> mContentDescriptionCache; private final TaskResourceLoadQueue mLoadQueue; private final IconLoader mIconLoader; private final BackgroundTaskLoader mLoader; private final HighResThumbnailLoader mHighResThumbnailLoader; @GuardedBy("this") Loading @@ -86,7 +81,6 @@ public class RecentsTaskLoader { private int mDefaultTaskBarBackgroundColor; private int mDefaultTaskViewBackgroundColor; private final BitmapDrawable mDefaultIcon; private EvictionCallback mClearActivityInfoOnEviction = new EvictionCallback() { @Override Loading @@ -99,16 +93,10 @@ public class RecentsTaskLoader { public RecentsTaskLoader(Context context, int maxThumbnailCacheSize, int maxIconCacheSize, int svelteLevel) { mContext = context; mMaxThumbnailCacheSize = maxThumbnailCacheSize; mMaxIconCacheSize = maxIconCacheSize; mSvelteLevel = svelteLevel; // Create the default assets Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); icon.eraseColor(0); mDefaultIcon = new BitmapDrawable(context.getResources(), icon); // Initialize the proxy, cache and loaders int numRecentTasks = ActivityManager.getMaxRecentTasksStatic(); mHighResThumbnailLoader = new HighResThumbnailLoader(ActivityManagerWrapper.getInstance(), Loading @@ -119,10 +107,17 @@ public class RecentsTaskLoader { mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction); mActivityInfoCache = new LruCache<>(numRecentTasks); mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mDefaultIcon, mIconLoader = createNewIconLoader(context, mIconCache, mActivityInfoCache); mLoader = new BackgroundTaskLoader(mLoadQueue, mIconLoader, mHighResThumbnailLoader::setTaskLoadQueueIdle); } protected IconLoader createNewIconLoader(Context context,TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { return new IconLoader.DefaultIconLoader(context, iconCache, activityInfoCache); } /** * Sets the default task bar/view colors if none are provided by the app. */ Loading Loading @@ -187,7 +182,7 @@ public class RecentsTaskLoader { */ public void loadTaskData(Task t) { Drawable icon = mIconCache.getAndInvalidateIfModified(t.key); icon = icon != null ? icon : mDefaultIcon; icon = icon != null ? icon : mIconLoader.getDefaultIcon(t.key.userId); mLoadQueue.addTask(t); t.notifyTaskDataLoaded(t.thumbnail, icon); } Loading @@ -195,7 +190,7 @@ public class RecentsTaskLoader { /** Releases the task resource data back into the pool. */ public void unloadTaskData(Task t) { mLoadQueue.removeTask(t); t.notifyTaskDataUnloaded(mDefaultIcon); t.notifyTaskDataUnloaded(mIconLoader.getDefaultIcon(t.key.userId)); } /** Completely removes the resource data from the pool. */ Loading @@ -205,7 +200,7 @@ public class RecentsTaskLoader { mActivityLabelCache.remove(t.key); mContentDescriptionCache.remove(t.key); if (notifyTaskDataUnloaded) { t.notifyTaskDataUnloaded(mDefaultIcon); t.notifyTaskDataUnloaded(mIconLoader.getDefaultIcon(t.key.userId)); } } Loading Loading @@ -326,35 +321,8 @@ public class RecentsTaskLoader { * Returns the cached task icon if the task key is not expired, updating the cache if it is. */ Drawable getAndUpdateActivityIcon(TaskKey taskKey, ActivityManager.TaskDescription td, Resources res, boolean loadIfNotCached) { // Return the cached activity icon if it exists Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey); if (icon != null) { return icon; } if (loadIfNotCached) { // Return and cache the task description icon if it exists icon = ActivityManagerWrapper.getInstance().getBadgedTaskDescriptionIcon(mContext, td, taskKey.userId, res); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } // Load the icon from the activity info and cache it ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey); if (activityInfo != null) { icon = ActivityManagerWrapper.getInstance().getBadgedActivityIcon(activityInfo, taskKey.userId); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } } } // We couldn't load any icon return null; boolean loadIfNotCached) { return mIconLoader.getAndInvalidateIfModified(taskKey, td, loadIfNotCached); } /** Loading Loading @@ -417,18 +385,7 @@ public class RecentsTaskLoader { * task key is expired. */ ActivityInfo getAndUpdateActivityInfo(TaskKey taskKey) { ComponentName cn = taskKey.getComponent(); ActivityInfo activityInfo = mActivityInfoCache.get(cn); if (activityInfo == null) { activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, taskKey.userId); if (cn == null || activityInfo == null) { Log.e(TAG, "Unexpected null component name or activity info: " + cn + ", " + activityInfo); return null; } mActivityInfoCache.put(cn, activityInfo); } return activityInfo; return mIconLoader.getAndUpdateActivityInfo(taskKey); } /** Loading packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +0 −61 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.shared.system; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; Loading @@ -40,25 +39,19 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.IconDrawableFactory; import android.util.Log; import android.view.IRecentsAnimationController; import android.view.IRecentsAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.WindowManagerGlobal; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.ThumbnailData; Loading @@ -74,14 +67,12 @@ public class ActivityManagerWrapper { private static final ActivityManagerWrapper sInstance = new ActivityManagerWrapper(); private final PackageManager mPackageManager; private final IconDrawableFactory mDrawableFactory; private final BackgroundExecutor mBackgroundExecutor; private final TaskStackChangeListeners mTaskStackChangeListeners; private ActivityManagerWrapper() { final Context context = AppGlobals.getInitialApplication(); mPackageManager = context.getPackageManager(); mDrawableFactory = IconDrawableFactory.newInstance(context); mBackgroundExecutor = BackgroundExecutor.get(); mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper()); } Loading Loading @@ -155,58 +146,6 @@ public class ActivityManagerWrapper { } } /** * @return the task description icon, loading and badging it if it necessary. */ public Drawable getBadgedTaskDescriptionIcon(Context context, ActivityManager.TaskDescription taskDescription, int userId, Resources res) { Bitmap tdIcon = taskDescription.getInMemoryIcon(); Drawable dIcon = null; if (tdIcon != null) { dIcon = new BitmapDrawable(res, tdIcon); } else if (taskDescription.getIconResource() != 0) { try { dIcon = context.getDrawable(taskDescription.getIconResource()); } catch (NotFoundException e) { Log.e(TAG, "Could not find icon drawable from resource", e); } } else { tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon( taskDescription.getIconFilename(), userId); if (tdIcon != null) { dIcon = new BitmapDrawable(res, tdIcon); } } if (dIcon != null) { return getBadgedIcon(dIcon, userId); } return null; } /** * @return the given icon for a user, badging if necessary. */ private Drawable getBadgedIcon(Drawable icon, int userId) { if (userId != UserHandle.myUserId()) { icon = mPackageManager.getUserBadgedIcon(icon, new UserHandle(userId)); } return icon; } /** * @return the activity icon for the ActivityInfo for a user, badging if necessary. */ public Drawable getBadgedActivityIcon(ActivityInfo info, int userId) { return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId); } /** * @return the application icon for the ApplicationInfo for a user, badging if necessary. */ public Drawable getBadgedApplicationIcon(ApplicationInfo appInfo, int userId) { return mDrawableFactory.getBadgedIcon(appInfo, userId); } /** * @return the activity label, badging if necessary. */ Loading Loading
packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/BackgroundTaskLoader.java +5 −37 Original line number Diff line number Diff line Loading @@ -17,15 +17,12 @@ package com.android.systemui.shared.recents.model; import android.content.Context; import android.content.pm.ActivityInfo; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; /** * Background task resource loader Loading @@ -40,8 +37,7 @@ class BackgroundTaskLoader implements Runnable { private final Handler mMainThreadHandler; private final TaskResourceLoadQueue mLoadQueue; private final TaskKeyLruCache<Drawable> mIconCache; private final BitmapDrawable mDefaultIcon; private final IconLoader mIconLoader; private boolean mStarted; private boolean mCancelled; Loading @@ -51,11 +47,9 @@ class BackgroundTaskLoader implements Runnable { /** Constructor, creates a new loading thread that loads task resources in the background */ public BackgroundTaskLoader(TaskResourceLoadQueue loadQueue, TaskKeyLruCache<Drawable> iconCache, BitmapDrawable defaultIcon, OnIdleChangedListener onIdleChangedListener) { IconLoader iconLoader, OnIdleChangedListener onIdleChangedListener) { mLoadQueue = loadQueue; mIconCache = iconCache; mDefaultIcon = defaultIcon; mIconLoader = iconLoader; mMainThreadHandler = new Handler(); mOnIdleChangedListener = onIdleChangedListener; mLoadThread = new HandlerThread("Recents-TaskResourceLoader", Loading Loading @@ -140,32 +134,7 @@ class BackgroundTaskLoader implements Runnable { // Load the next item from the queue final Task t = mLoadQueue.nextTask(); if (t != null) { Drawable cachedIcon = mIconCache.get(t.key); // Load the icon if it is stale or we haven't cached one yet if (cachedIcon == null) { cachedIcon = ActivityManagerWrapper.getInstance().getBadgedTaskDescriptionIcon( mContext, t.taskDescription, t.key.userId, mContext.getResources()); if (cachedIcon == null) { ActivityInfo info = PackageManagerWrapper.getInstance().getActivityInfo( t.key.getComponent(), t.key.userId); if (info != null) { if (DEBUG) Log.d(TAG, "Loading icon: " + t.key); cachedIcon = ActivityManagerWrapper.getInstance().getBadgedActivityIcon( info, t.key.userId); } } if (cachedIcon == null) { cachedIcon = mDefaultIcon; } // At this point, even if we can't load the icon, we will set the // default icon. mIconCache.put(t.key, cachedIcon); } final Drawable icon = mIconLoader.getIcon(t); if (DEBUG) Log.d(TAG, "Loading thumbnail: " + t.key); final ThumbnailData thumbnailData = ActivityManagerWrapper.getInstance().getTaskThumbnail(t.key.id, Loading @@ -173,9 +142,8 @@ class BackgroundTaskLoader implements Runnable { if (!mCancelled) { // Notify that the task data has changed final Drawable finalIcon = cachedIcon; mMainThreadHandler.post( () -> t.notifyTaskDataLoaded(thumbnailData, finalIcon)); () -> t.notifyTaskDataLoaded(thumbnailData, icon)); } } } Loading
packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/IconLoader.java 0 → 100644 +183 −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.shared.recents.model; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.UserHandle; import android.util.IconDrawableFactory; import android.util.Log; import android.util.LruCache; import com.android.systemui.shared.system.PackageManagerWrapper; public abstract class IconLoader { private static final String TAG = "IconLoader"; protected final Context mContext; protected final TaskKeyLruCache<Drawable> mIconCache; protected final LruCache<ComponentName, ActivityInfo> mActivityInfoCache; public IconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { mContext = context; mIconCache = iconCache; mActivityInfoCache = activityInfoCache; } /** * Returns the activity info for the given task key, retrieving one from the system if the * task key is expired. * * TODO: Move this to an ActivityInfoCache class */ public ActivityInfo getAndUpdateActivityInfo(Task.TaskKey taskKey) { ComponentName cn = taskKey.getComponent(); ActivityInfo activityInfo = mActivityInfoCache.get(cn); if (activityInfo == null) { activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, taskKey.userId); if (cn == null || activityInfo == null) { Log.e(TAG, "Unexpected null component name or activity info: " + cn + ", " + activityInfo); return null; } mActivityInfoCache.put(cn, activityInfo); } return activityInfo; } public Drawable getIcon(Task t) { Drawable cachedIcon = mIconCache.get(t.key); if (cachedIcon == null) { cachedIcon = createNewIconForTask(t.key, t.taskDescription, true /* returnDefault */); mIconCache.put(t.key, cachedIcon); } return cachedIcon; } /** * Returns the cached task icon if the task key is not expired, updating the cache if it is. */ public Drawable getAndInvalidateIfModified(Task.TaskKey taskKey, ActivityManager.TaskDescription td, boolean loadIfNotCached) { // Return the cached activity icon if it exists Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey); if (icon != null) { return icon; } if (loadIfNotCached) { icon = createNewIconForTask(taskKey, td, false /* returnDefault */); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } } // We couldn't load any icon return null; } private Drawable createNewIconForTask(Task.TaskKey taskKey, ActivityManager.TaskDescription desc, boolean returnDefault) { int userId = taskKey.userId; Bitmap tdIcon = desc.getInMemoryIcon(); if (tdIcon != null) { return createDrawableFromBitmap(tdIcon, userId); } if (desc.getIconResource() != 0) { // TODO: Use task context here try { return createBadgedDrawable(mContext.getDrawable(desc.getIconResource()), userId); } catch (Resources.NotFoundException e) { Log.e(TAG, "Could not find icon drawable from resource", e); } } tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon( desc.getIconFilename(), userId); if (tdIcon != null) { return createDrawableFromBitmap(tdIcon, userId); } // Load the icon from the activity info and cache it ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey); if (activityInfo != null) { Drawable icon = getBadgedActivityIcon(activityInfo, userId); if (icon != null) { return icon; } } // At this point, even if we can't load the icon, we will set the default icon. return returnDefault ? getDefaultIcon(userId) : null; } public abstract Drawable getDefaultIcon(int userId); protected Drawable createDrawableFromBitmap(Bitmap icon, int userId) { return createBadgedDrawable(new BitmapDrawable(mContext.getResources(), icon), userId); } protected abstract Drawable createBadgedDrawable(Drawable icon, int userId); /** * @return the activity icon for the ActivityInfo for a user, badging if necessary. */ protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId); public static class DefaultIconLoader extends IconLoader { private final BitmapDrawable mDefaultIcon; private final IconDrawableFactory mDrawableFactory; public DefaultIconLoader(Context context, TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { super(context, iconCache, activityInfoCache); // Create the default assets Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); icon.eraseColor(0); mDefaultIcon = new BitmapDrawable(context.getResources(), icon); mDrawableFactory = IconDrawableFactory.newInstance(context); } @Override public Drawable getDefaultIcon(int userId) { return mDefaultIcon; } @Override protected Drawable createBadgedDrawable(Drawable icon, int userId) { if (userId != UserHandle.myUserId()) { icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(userId)); } return icon; } @Override protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId) { return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId); } } }
packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoadPlan.java +2 −2 Original line number Diff line number Diff line Loading @@ -123,7 +123,7 @@ public class RecentsTaskLoadPlan { ? loader.getAndUpdateContentDescription(taskKey, t.taskDescription) : ""; Drawable icon = isStackTask ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false) ? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, false) : null; ThumbnailData thumbnail = loader.getAndUpdateThumbnail(taskKey, false /* loadIfNotCached */, false /* storeInCache */); Loading Loading @@ -179,7 +179,7 @@ public class RecentsTaskLoadPlan { if (opts.loadIcons && (isRunningTask || isVisibleTask)) { if (task.icon == null) { task.icon = loader.getAndUpdateActivityIcon(taskKey, task.taskDescription, res, task.icon = loader.getAndUpdateActivityIcon(taskKey, task.taskDescription, true); } } Loading
packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/RecentsTaskLoader.java +15 −58 Original line number Diff line number Diff line Loading @@ -21,9 +21,6 @@ import android.content.ComponentCallbacks2; import android.content.ComponentName; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Looper; import android.os.Trace; Loading @@ -36,7 +33,6 @@ import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan.PreloadOpti import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.TaskKeyLruCache.EvictionCallback; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; import java.io.PrintWriter; import java.util.Map; Loading @@ -61,8 +57,6 @@ public class RecentsTaskLoader { // Disable all thumbnail loading. public static final int SVELTE_DISABLE_LOADING = 3; private final Context mContext; // This activity info LruCache is useful because it can be expensive to retrieve ActivityInfos // for many tasks, which we use to get the activity labels and icons. Unlike the other caches // below, this is per-package so we can't invalidate the items in the cache based on the last Loading @@ -73,6 +67,7 @@ public class RecentsTaskLoader { private final TaskKeyLruCache<String> mActivityLabelCache; private final TaskKeyLruCache<String> mContentDescriptionCache; private final TaskResourceLoadQueue mLoadQueue; private final IconLoader mIconLoader; private final BackgroundTaskLoader mLoader; private final HighResThumbnailLoader mHighResThumbnailLoader; @GuardedBy("this") Loading @@ -86,7 +81,6 @@ public class RecentsTaskLoader { private int mDefaultTaskBarBackgroundColor; private int mDefaultTaskViewBackgroundColor; private final BitmapDrawable mDefaultIcon; private EvictionCallback mClearActivityInfoOnEviction = new EvictionCallback() { @Override Loading @@ -99,16 +93,10 @@ public class RecentsTaskLoader { public RecentsTaskLoader(Context context, int maxThumbnailCacheSize, int maxIconCacheSize, int svelteLevel) { mContext = context; mMaxThumbnailCacheSize = maxThumbnailCacheSize; mMaxIconCacheSize = maxIconCacheSize; mSvelteLevel = svelteLevel; // Create the default assets Bitmap icon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8); icon.eraseColor(0); mDefaultIcon = new BitmapDrawable(context.getResources(), icon); // Initialize the proxy, cache and loaders int numRecentTasks = ActivityManager.getMaxRecentTasksStatic(); mHighResThumbnailLoader = new HighResThumbnailLoader(ActivityManagerWrapper.getInstance(), Loading @@ -119,10 +107,17 @@ public class RecentsTaskLoader { mContentDescriptionCache = new TaskKeyLruCache<>(numRecentTasks, mClearActivityInfoOnEviction); mActivityInfoCache = new LruCache<>(numRecentTasks); mLoader = new BackgroundTaskLoader(mLoadQueue, mIconCache, mDefaultIcon, mIconLoader = createNewIconLoader(context, mIconCache, mActivityInfoCache); mLoader = new BackgroundTaskLoader(mLoadQueue, mIconLoader, mHighResThumbnailLoader::setTaskLoadQueueIdle); } protected IconLoader createNewIconLoader(Context context,TaskKeyLruCache<Drawable> iconCache, LruCache<ComponentName, ActivityInfo> activityInfoCache) { return new IconLoader.DefaultIconLoader(context, iconCache, activityInfoCache); } /** * Sets the default task bar/view colors if none are provided by the app. */ Loading Loading @@ -187,7 +182,7 @@ public class RecentsTaskLoader { */ public void loadTaskData(Task t) { Drawable icon = mIconCache.getAndInvalidateIfModified(t.key); icon = icon != null ? icon : mDefaultIcon; icon = icon != null ? icon : mIconLoader.getDefaultIcon(t.key.userId); mLoadQueue.addTask(t); t.notifyTaskDataLoaded(t.thumbnail, icon); } Loading @@ -195,7 +190,7 @@ public class RecentsTaskLoader { /** Releases the task resource data back into the pool. */ public void unloadTaskData(Task t) { mLoadQueue.removeTask(t); t.notifyTaskDataUnloaded(mDefaultIcon); t.notifyTaskDataUnloaded(mIconLoader.getDefaultIcon(t.key.userId)); } /** Completely removes the resource data from the pool. */ Loading @@ -205,7 +200,7 @@ public class RecentsTaskLoader { mActivityLabelCache.remove(t.key); mContentDescriptionCache.remove(t.key); if (notifyTaskDataUnloaded) { t.notifyTaskDataUnloaded(mDefaultIcon); t.notifyTaskDataUnloaded(mIconLoader.getDefaultIcon(t.key.userId)); } } Loading Loading @@ -326,35 +321,8 @@ public class RecentsTaskLoader { * Returns the cached task icon if the task key is not expired, updating the cache if it is. */ Drawable getAndUpdateActivityIcon(TaskKey taskKey, ActivityManager.TaskDescription td, Resources res, boolean loadIfNotCached) { // Return the cached activity icon if it exists Drawable icon = mIconCache.getAndInvalidateIfModified(taskKey); if (icon != null) { return icon; } if (loadIfNotCached) { // Return and cache the task description icon if it exists icon = ActivityManagerWrapper.getInstance().getBadgedTaskDescriptionIcon(mContext, td, taskKey.userId, res); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } // Load the icon from the activity info and cache it ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey); if (activityInfo != null) { icon = ActivityManagerWrapper.getInstance().getBadgedActivityIcon(activityInfo, taskKey.userId); if (icon != null) { mIconCache.put(taskKey, icon); return icon; } } } // We couldn't load any icon return null; boolean loadIfNotCached) { return mIconLoader.getAndInvalidateIfModified(taskKey, td, loadIfNotCached); } /** Loading Loading @@ -417,18 +385,7 @@ public class RecentsTaskLoader { * task key is expired. */ ActivityInfo getAndUpdateActivityInfo(TaskKey taskKey) { ComponentName cn = taskKey.getComponent(); ActivityInfo activityInfo = mActivityInfoCache.get(cn); if (activityInfo == null) { activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, taskKey.userId); if (cn == null || activityInfo == null) { Log.e(TAG, "Unexpected null component name or activity info: " + cn + ", " + activityInfo); return null; } mActivityInfoCache.put(cn, activityInfo); } return activityInfo; return mIconLoader.getAndUpdateActivityInfo(taskKey); } /** Loading
packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java +0 −61 Original line number Diff line number Diff line Loading @@ -17,7 +17,6 @@ package com.android.systemui.shared.system; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; Loading @@ -40,25 +39,19 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.util.IconDrawableFactory; import android.util.Log; import android.view.IRecentsAnimationController; import android.view.IRecentsAnimationRunner; import android.view.RemoteAnimationTarget; import android.view.WindowManagerGlobal; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.ThumbnailData; Loading @@ -74,14 +67,12 @@ public class ActivityManagerWrapper { private static final ActivityManagerWrapper sInstance = new ActivityManagerWrapper(); private final PackageManager mPackageManager; private final IconDrawableFactory mDrawableFactory; private final BackgroundExecutor mBackgroundExecutor; private final TaskStackChangeListeners mTaskStackChangeListeners; private ActivityManagerWrapper() { final Context context = AppGlobals.getInitialApplication(); mPackageManager = context.getPackageManager(); mDrawableFactory = IconDrawableFactory.newInstance(context); mBackgroundExecutor = BackgroundExecutor.get(); mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper()); } Loading Loading @@ -155,58 +146,6 @@ public class ActivityManagerWrapper { } } /** * @return the task description icon, loading and badging it if it necessary. */ public Drawable getBadgedTaskDescriptionIcon(Context context, ActivityManager.TaskDescription taskDescription, int userId, Resources res) { Bitmap tdIcon = taskDescription.getInMemoryIcon(); Drawable dIcon = null; if (tdIcon != null) { dIcon = new BitmapDrawable(res, tdIcon); } else if (taskDescription.getIconResource() != 0) { try { dIcon = context.getDrawable(taskDescription.getIconResource()); } catch (NotFoundException e) { Log.e(TAG, "Could not find icon drawable from resource", e); } } else { tdIcon = ActivityManager.TaskDescription.loadTaskDescriptionIcon( taskDescription.getIconFilename(), userId); if (tdIcon != null) { dIcon = new BitmapDrawable(res, tdIcon); } } if (dIcon != null) { return getBadgedIcon(dIcon, userId); } return null; } /** * @return the given icon for a user, badging if necessary. */ private Drawable getBadgedIcon(Drawable icon, int userId) { if (userId != UserHandle.myUserId()) { icon = mPackageManager.getUserBadgedIcon(icon, new UserHandle(userId)); } return icon; } /** * @return the activity icon for the ActivityInfo for a user, badging if necessary. */ public Drawable getBadgedActivityIcon(ActivityInfo info, int userId) { return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId); } /** * @return the application icon for the ApplicationInfo for a user, badging if necessary. */ public Drawable getBadgedApplicationIcon(ApplicationInfo appInfo, int userId) { return mDrawableFactory.getBadgedIcon(appInfo, userId); } /** * @return the activity label, badging if necessary. */ Loading