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

Commit af42c842 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Extrating out icon generation logic so that it can customized

Test: Created jar and varified launcher is works properly
Change-Id: Ic07083d6394bb65d857b665fd86fa67f6323ed7b
parent 3c94405a
Loading
Loading
Loading
Loading
+5 −37
Original line number Diff line number Diff line
@@ -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
@@ -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;
@@ -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",
@@ -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,
@@ -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));
            }
        }
    }
+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);
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -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 */);
@@ -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);
                }
            }
+15 −58
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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
@@ -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")
@@ -86,7 +81,6 @@ public class RecentsTaskLoader {

    private int mDefaultTaskBarBackgroundColor;
    private int mDefaultTaskViewBackgroundColor;
    private final BitmapDrawable mDefaultIcon;

    private EvictionCallback mClearActivityInfoOnEviction = new EvictionCallback() {
        @Override
@@ -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(),
@@ -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.
     */
@@ -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);
    }
@@ -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. */
@@ -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));
        }
    }

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

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

    /**
+0 −61
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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());
    }
@@ -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