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

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

Removing some unused classes

Test: Everything builds
Change-Id: I92f630b12d2247ad8cf29bb5e2a4c190aa27bced
parent e428a2cc
Loading
Loading
Loading
Loading
+0 −197
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 static android.content.pm.PackageManager.MATCH_ANY_USER;

import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
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, desc);
        }
        if (desc.getIconResource() != 0) {
            try {
                PackageManager pm = mContext.getPackageManager();
                ApplicationInfo appInfo = pm.getApplicationInfo(taskKey.getPackageName(),
                        MATCH_ANY_USER);
                Resources res = pm.getResourcesForApplication(appInfo);
                return createBadgedDrawable(res.getDrawable(desc.getIconResource(), null), userId,
                        desc);
            } catch (Resources.NotFoundException|PackageManager.NameNotFoundException 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, desc);
        }

        // Load the icon from the activity info and cache it
        ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
        if (activityInfo != null) {
            Drawable icon = getBadgedActivityIcon(activityInfo, userId, desc);
            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,
            ActivityManager.TaskDescription desc) {
        return createBadgedDrawable(
                new BitmapDrawable(mContext.getResources(), icon), userId, desc);
    }

    protected abstract Drawable createBadgedDrawable(Drawable icon, int userId,
            ActivityManager.TaskDescription desc);

    /**
     * @return the activity icon for the ActivityInfo for a user, badging if necessary.
     */
    protected abstract Drawable getBadgedActivityIcon(ActivityInfo info, int userId,
            ActivityManager.TaskDescription desc);

    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,
                ActivityManager.TaskDescription desc) {
            if (userId != UserHandle.myUserId()) {
                icon = mContext.getPackageManager().getUserBadgedIcon(icon, new UserHandle(userId));
            }
            return icon;
        }

        @Override
        protected Drawable getBadgedActivityIcon(ActivityInfo info, int userId,
                ActivityManager.TaskDescription desc) {
            return mDrawableFactory.getBadgedIcon(info, info.applicationInfo, userId);
        }
    }
}
+0 −101
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.util.Log;
import android.util.SparseArray;

import com.android.systemui.shared.recents.model.Task.TaskKey;

import java.util.ArrayList;
import java.util.Collection;

/**
 * Base class for both strong and LRU task key cache.
 */
public abstract class TaskKeyCache<V> {

    protected static final String TAG = "TaskKeyCache";

    protected final SparseArray<TaskKey> mKeys = new SparseArray<>();

    /**
     * Gets a specific entry in the cache with the specified key, regardless of whether the cached
     * value is valid or not.
     */
    public final synchronized V get(TaskKey key) {
        return getCacheEntry(key.id);
    }

    /**
     * Returns the value only if the key is valid (has not been updated since the last time it was
     * in the cache)
     */
    public final synchronized V getAndInvalidateIfModified(TaskKey key) {
        TaskKey lastKey = mKeys.get(key.id);
        if (lastKey != null) {
            if ((lastKey.windowingMode != key.windowingMode) ||
                    (lastKey.lastActiveTime != key.lastActiveTime)) {
                // The task has updated (been made active since the last time it was put into the
                // LRU cache) or the stack id for the task has changed, invalidate that cache item
                remove(key);
                return null;
            }
        }
        // Either the task does not exist in the cache, or the last active time is the same as
        // the key specified, so return what is in the cache
        return getCacheEntry(key.id);
    }

    /** Puts an entry in the cache for a specific key. */
    public final synchronized void put(TaskKey key, V value) {
        if (key == null || value == null) {
            Log.e(TAG, "Unexpected null key or value: " + key + ", " + value);
            return;
        }
        mKeys.put(key.id, key);
        putCacheEntry(key.id, value);
    }


    /** Removes a cache entry for a specific key. */
    public final synchronized void remove(TaskKey key) {
        // Remove the key after the cache value because we need it to make the callback
        removeCacheEntry(key.id);
        mKeys.remove(key.id);
    }

    /** @return {@link Collection} of {@link TaskKey} */
    public Collection<TaskKey> getValues() {
        Collection<TaskKey> result = new ArrayList<>(mKeys.size());
        for (int i = 0; i < mKeys.size(); i++) {
            result.add(mKeys.valueAt(i));
        }
        return result;
    }

    /** Removes all the entries in the cache. */
    public final synchronized void evictAll() {
        evictAllCache();
        mKeys.clear();
    }

    protected abstract V getCacheEntry(int id);
    protected abstract void putCacheEntry(int id, V value);
    protected abstract void removeCacheEntry(int id);
    protected abstract void evictAllCache();
}
+0 −100
Original line number Diff line number Diff line
/*
 * 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.shared.recents.model;

import android.util.LruCache;

import com.android.systemui.shared.recents.model.Task.TaskKey;

import java.io.PrintWriter;

/**
 * A mapping of {@link TaskKey} to value, with additional LRU functionality where the least
 * recently referenced key/values will be evicted as more values than the given cache size are
 * inserted.
 *
 * In addition, this also allows the caller to invalidate cached values for keys that have since
 * changed.
 */
public class TaskKeyLruCache<V> extends TaskKeyCache<V> {

    public interface EvictionCallback {
        void onEntryEvicted(TaskKey key);
    }

    private final LruCache<Integer, V> mCache;
    private final EvictionCallback mEvictionCallback;

    public TaskKeyLruCache(int cacheSize) {
        this(cacheSize, null);
    }

    public TaskKeyLruCache(int cacheSize, EvictionCallback evictionCallback) {
        mEvictionCallback = evictionCallback;
        mCache = new LruCache<Integer, V>(cacheSize) {

            @Override
            protected void entryRemoved(boolean evicted, Integer taskId, V oldV, V newV) {
                if (mEvictionCallback != null && evicted) {
                    mEvictionCallback.onEntryEvicted(mKeys.get(taskId));
                }

                // Only remove from mKeys on cache remove, not a cache update.
                if (newV == null) {
                    mKeys.remove(taskId);
                }
            }
        };
    }

    /** Trims the cache to a specific size */
    public final void trimToSize(int cacheSize) {
        mCache.trimToSize(cacheSize);
    }

    public void dump(String prefix, PrintWriter writer) {
        String innerPrefix = prefix + "  ";

        writer.print(prefix); writer.print(TAG);
        writer.print(" numEntries="); writer.print(mKeys.size());
        writer.println();
        int keyCount = mKeys.size();
        for (int i = 0; i < keyCount; i++) {
            writer.print(innerPrefix); writer.println(mKeys.get(mKeys.keyAt(i)));
        }
    }

    @Override
    protected V getCacheEntry(int id) {
        return mCache.get(id);
    }

    @Override
    protected void putCacheEntry(int id, V value) {
        mCache.put(id, value);
    }

    @Override
    protected void removeCacheEntry(int id) {
        mCache.remove(id);
    }

    @Override
    protected void evictAllCache() {
        mCache.evictAll();
    }
}
+0 −140
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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 static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import android.test.suitebuilder.annotation.SmallTest;

import com.android.systemui.SysuiTestCase;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

@SmallTest
@RunWith(MockitoJUnitRunner.class)
public class TaskKeyLruCacheTest extends SysuiTestCase {
    private static int sCacheSize = 3;
    private static int sIdTask1 = 1;
    private static int sIdTask2 = 2;
    private static int sIdTask3 = 3;
    private static int sIdUser1 = 1;

    TaskKeyLruCache.EvictionCallback mEvictionCallback;

    TaskKeyLruCache<Integer> mCache;
    private Task.TaskKey mKey1;
    private Task.TaskKey mKey2;
    private Task.TaskKey mKey3;

    @Before
    public void setup() {
        mEvictionCallback = mock(TaskKeyLruCache.EvictionCallback.class);
        mCache = new TaskKeyLruCache<>(sCacheSize, mEvictionCallback);

        mKey1 = new Task.TaskKey(sIdTask1, 0, null, null, sIdUser1, System.currentTimeMillis());
        mKey2 = new Task.TaskKey(sIdTask2, 0, null, null, sIdUser1, System.currentTimeMillis());
        mKey3 = new Task.TaskKey(sIdTask3, 0, null, null, sIdUser1, System.currentTimeMillis());
    }

    @Test
    public void addSingleItem_get_success() {
        mCache.put(mKey1, 1);

        assertEquals(1, (int) mCache.get(mKey1));
    }

    @Test
    public void addSingleItem_getUninsertedItem_returnsNull() {
        mCache.put(mKey1, 1);

        assertNull(mCache.get(mKey2));
    }

    @Test
    public void emptyCache_get_returnsNull() {
        assertNull(mCache.get(mKey1));
    }

    @Test
    public void updateItem_get_returnsSecond() {
        mCache.put(mKey1, 1);
        mCache.put(mKey1, 2);

        assertEquals(2, (int) mCache.get(mKey1));
        assertEquals(1, mCache.mKeys.size());
    }

    @Test
    public void fillCache_put_evictsOldest() {
        mCache.put(mKey1, 1);
        mCache.put(mKey2, 2);
        mCache.put(mKey3, 3);
        Task.TaskKey key4 = new Task.TaskKey(sIdTask3 + 1, 0,
                null, null, sIdUser1, System.currentTimeMillis());
        mCache.put(key4, 4);

        assertNull(mCache.get(mKey1));
        assertEquals(3, mCache.mKeys.size());
        assertEquals(mKey2, mCache.mKeys.valueAt(0));
        verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
    }

    @Test
    public void fillCache_remove_success() {
        mCache.put(mKey1, 1);
        mCache.put(mKey2, 2);
        mCache.put(mKey3, 3);

        mCache.remove(mKey2);

        assertNull(mCache.get(mKey2));
        assertEquals(2, mCache.mKeys.size());
        verify(mEvictionCallback, times(0)).onEntryEvicted(mKey2);
    }

    @Test
    public void put_evictionCallback_notCalled() {
        mCache.put(mKey1, 1);
        verify(mEvictionCallback, times(0)).onEntryEvicted(mKey1);
    }

    @Test
    public void evictAll_evictionCallback_called() {
        mCache.put(mKey1, 1);
        mCache.evictAllCache();
        verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
    }

    @Test
    public void trimAll_evictionCallback_called() {
        mCache.put(mKey1, 1);
        mCache.put(mKey2, 2);
        mCache.trimToSize(-1);
        verify(mEvictionCallback, times(1)).onEntryEvicted(mKey1);
        verify(mEvictionCallback, times(1)).onEntryEvicted(mKey2);

    }
}