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

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

Linking various settings that control icon cache to icon state

Also separating icon provider for recents from Launcher as it used a fixed size

Bug: 183641907
Test: Verified on device
Change-Id: I6ea3caa0066d1483bfb8a81f0e8aaa472c813afe
parent e4103403
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.launcher3.model;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.formatElapsedTime;

import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
@@ -252,12 +251,10 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange
    }

    @Override
    public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
        if ((changeFlags & CHANGE_FLAG_GRID) != 0) {
    public void onIdpChanged(InvariantDeviceProfile profile) {
        // Reinitialize everything
        Executors.MODEL_EXECUTOR.execute(this::recreatePredictors);
    }
    }

    private void onAppTargetEvent(AppTargetEvent event, int client) {
        PredictorState state = client == CONTAINER_PREDICTION ? mAllAppsState : mHotseatState;
+16 −8
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.os.UserHandle;
import androidx.annotation.VisibleForTesting;

import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.IconProvider.IconChangeListener;
import com.android.launcher3.util.Executors.SimpleThreadFactory;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.systemui.shared.recents.model.Task;
@@ -49,7 +50,7 @@ import java.util.function.Consumer;
 * Singleton class to load and manage recents model.
 */
@TargetApi(Build.VERSION_CODES.O)
public class RecentsModel extends TaskStackChangeListener {
public class RecentsModel extends TaskStackChangeListener implements IconChangeListener {

    // We do not need any synchronization for this variable as its only written on UI thread.
    public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
@@ -69,12 +70,13 @@ public class RecentsModel extends TaskStackChangeListener {
        mContext = context;
        mTaskList = new RecentTasksList(MAIN_EXECUTOR,
                new KeyguardManagerCompat(context), ActivityManagerWrapper.getInstance());
        mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR);

        IconProvider iconProvider = new IconProvider(context);
        mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider);
        mThumbnailCache = new TaskThumbnailCache(context, RECENTS_MODEL_EXECUTOR);

        ActivityManagerWrapper.getInstance().registerTaskStackListener(this);
        IconProvider.registerIconChangeListener(context,
                this::onPackageIconChanged, MAIN_EXECUTOR.getHandler());
        iconProvider.registerIconChangeListener(this, MAIN_EXECUTOR.getHandler());
    }

    public TaskIconCache getIconCache() {
@@ -183,15 +185,21 @@ public class RecentsModel extends TaskStackChangeListener {
        if (level == ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
            // Clear everything once we reach a low-mem situation
            mThumbnailCache.clear();
            mIconCache.clear();
            mIconCache.clearCache();
        }
    }

    private void onPackageIconChanged(String pkg, UserHandle user) {
        mIconCache.invalidateCacheEntries(pkg, user);
    @Override
    public void onAppIconChanged(String packageName, UserHandle user) {
        mIconCache.invalidateCacheEntries(packageName, user);
        for (int i = mThumbnailChangeListeners.size() - 1; i >= 0; i--) {
            mThumbnailChangeListeners.get(i).onTaskIconChanged(pkg, user);
            mThumbnailChangeListeners.get(i).onTaskIconChanged(packageName, user);
        }
    }

    @Override
    public void onSystemIconStateChanged(String iconState) {
        mIconCache.clearCache();
    }

    /**
+47 −12
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.quickstep;

import static com.android.launcher3.uioverrides.QuickstepLauncher.GO_LOW_RAM_RECENTS_ENABLED;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;

import android.app.ActivityManager.TaskDescription;
import android.content.Context;
@@ -35,9 +36,12 @@ import androidx.annotation.WorkerThread;

import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.icons.BaseIconFactory;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.TaskKeyLruCache;
@@ -52,7 +56,7 @@ import java.util.function.Consumer;
/**
 * Manages the caching of task icons and related data.
 */
public class TaskIconCache {
public class TaskIconCache implements DisplayInfoChangeListener {

    private final Executor mBgExecutor;
    private final AccessibilityManager mAccessibilityManager;
@@ -62,15 +66,27 @@ public class TaskIconCache {
    private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
    private final IconProvider mIconProvider;

    public TaskIconCache(Context context, Executor bgExecutor) {
    private BaseIconFactory mIconFactory;

    public TaskIconCache(Context context, Executor bgExecutor, IconProvider iconProvider) {
        mContext = context;
        mBgExecutor = bgExecutor;
        mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
        mIconProvider = iconProvider;

        Resources res = context.getResources();
        int cacheSize = res.getInteger(R.integer.recentsIconCacheSize);

        mIconCache = new TaskKeyLruCache<>(cacheSize);
        mIconProvider = new IconProvider(context);

        DisplayController.INSTANCE.get(mContext).addChangeListener(this);
    }

    @Override
    public void onDisplayInfoChanged(Context context, Info info, int flags) {
        if ((flags & CHANGE_DENSITY) != 0) {
            clearCache();
        }
    }

    /**
@@ -104,8 +120,11 @@ public class TaskIconCache {
        return request;
    }

    public void clear() {
        mIconCache.evictAll();
    /**
     * Clears the icon cache
     */
    public void clearCache() {
        mBgExecutor.execute(this::resetFactory);
    }

    void onTaskRemoved(TaskKey taskKey) {
@@ -193,8 +212,8 @@ public class TaskIconCache {
        synchronized (mDefaultIcons) {
            BitmapInfo info = mDefaultIcons.get(userId);
            if (info == null) {
                try (LauncherIcons la = LauncherIcons.obtain(mContext)) {
                    info = la.makeDefaultIcon(UserHandle.of(userId));
                try (BaseIconFactory bif = getIconFactory()) {
                    info = bif.makeDefaultIcon(UserHandle.of(userId));
                }
                mDefaultIcons.put(userId, info);
            }
@@ -205,16 +224,32 @@ public class TaskIconCache {
    @WorkerThread
    private BitmapInfo getBitmapInfo(Drawable drawable, int userId,
            int primaryColor, boolean isInstantApp) {
        try (LauncherIcons la = LauncherIcons.obtain(mContext)) {
            la.disableColorExtraction();
            la.setWrapperBackgroundColor(primaryColor);
        try (BaseIconFactory bif = getIconFactory()) {
            bif.disableColorExtraction();
            bif.setWrapperBackgroundColor(primaryColor);

            // User version code O, so that the icon is always wrapped in an adaptive icon container
            return la.createBadgedIconBitmap(drawable, UserHandle.of(userId),
            return bif.createBadgedIconBitmap(drawable, UserHandle.of(userId),
                    Build.VERSION_CODES.O, isInstantApp);
        }
    }

    @WorkerThread
    private BaseIconFactory getIconFactory() {
        if (mIconFactory == null) {
            mIconFactory = new BaseIconFactory(mContext,
                    DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
                    mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
        }
        return mIconFactory;
    }

    @WorkerThread
    private void resetFactory() {
        mIconFactory = null;
        mIconCache.evictAll();
    }

    private static class TaskCacheEntry {
        public Drawable icon;
        public String contentDescription = "";
+1 −15
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static android.view.View.MeasureSpec.makeMeasureSpec;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
@@ -171,8 +170,7 @@ import java.util.function.Consumer;
public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>,
        STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
        TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
        InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener,
        SplitScreenBounds.OnChangeListener {
        TaskVisualsChangeListener, SplitScreenBounds.OnChangeListener {

    public static final FloatProperty<RecentsView> CONTENT_ALPHA =
            new FloatProperty<RecentsView>("contentAlpha") {
@@ -705,16 +703,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        updateTaskStackListenerState();
    }

    @Override
    public void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) {
        if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) == 0) {
            return;
        }
        mModel.getIconCache().clear();
        unloadVisibleTaskData(TaskView.FLAG_UPDATE_ICON);
        loadVisibleTaskData(TaskView.FLAG_UPDATE_ICON);
    }

    public void init(OverviewActionsView actionsView, SplitPlaceholderView splitPlaceholderView) {
        mActionsView = actionsView;
        mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
@@ -739,7 +727,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mSyncTransactionApplier = new SurfaceTransactionApplier(this);
        mLiveTileParams.setSyncTransactionApplier(mSyncTransactionApplier);
        RecentsModel.INSTANCE.get(getContext()).addThumbnailChangeListener(this);
        mIdp.addOnChangeListener(this);
        mIPipAnimationListener.setActivity(mActivity);
        SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
                mIPipAnimationListener);
@@ -758,7 +745,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mSyncTransactionApplier = null;
        mLiveTileParams.setSyncTransactionApplier(null);
        RecentsModel.INSTANCE.get(getContext()).removeThumbnailChangeListener(this);
        mIdp.removeOnChangeListener(this);
        SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(null);
        SplitScreenBounds.INSTANCE.removeOnChangeListener(this);
        mIPipAnimationListener.setActivity(null);
+5 −81
Original line number Diff line number Diff line
@@ -17,20 +17,16 @@
package com.android.launcher3;

import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.getDevicePrefs;
import static com.android.launcher3.Utilities.getPointString;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TWO_PANEL_HOME;
import static com.android.launcher3.util.DisplayController.CHANGE_DENSITY;
import static com.android.launcher3.util.DisplayController.CHANGE_SUPPORTED_BOUNDS;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;

import android.annotation.TargetApi;
import android.appwidget.AppWidgetHostView;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
@@ -49,7 +45,6 @@ import android.view.Display;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.launcher3.graphics.IconShape;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
@@ -83,11 +78,6 @@ public class InvariantDeviceProfile {

    private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;

    public static final int CHANGE_FLAG_GRID = 1 << 0;
    public static final int CHANGE_FLAG_ICON_PARAMS = 1 << 1;

    public static final String KEY_ICON_PATH_REF = "pref_icon_shape_path";

    // Constants that affects the interpolation curve between statically defined device profile
    // buckets.
    private static final float KNEARESTNEIGHBOR = 3;
@@ -96,9 +86,6 @@ public class InvariantDeviceProfile {
    // used to offset float not being able to express extremely small weights in extreme cases.
    private static final float WEIGHT_EFFICIENT = 100000f;

    private static final int CONFIG_ICON_MASK_RES_ID = Resources.getSystem().getIdentifier(
            "config_icon_mask", "string", "android");

    /**
     * Number of icons per row and column in the workspace.
     */
@@ -111,7 +98,6 @@ public class InvariantDeviceProfile {
    public int numFolderRows;
    public int numFolderColumns;
    public float iconSize;
    public String iconShapePath;
    public float landscapeIconSize;
    public float landscapeIconTextSize;
    public int iconBitmapSize;
@@ -162,7 +148,6 @@ public class InvariantDeviceProfile {
    public Rect defaultWidgetPadding;

    private final ArrayList<OnIDPChangeListener> mChangeListeners = new ArrayList<>();
    private OverlayMonitor mOverlayMonitor;

    @VisibleForTesting
    public InvariantDeviceProfile() {}
@@ -173,7 +158,6 @@ public class InvariantDeviceProfile {
        numFolderRows = p.numFolderRows;
        numFolderColumns = p.numFolderColumns;
        iconSize = p.iconSize;
        iconShapePath = p.iconShapePath;
        landscapeIconSize = p.landscapeIconSize;
        iconBitmapSize = p.iconBitmapSize;
        iconTextSize = p.iconTextSize;
@@ -193,7 +177,6 @@ public class InvariantDeviceProfile {
        defaultLayoutId = p.defaultLayoutId;
        demoModeLayoutId = p.demoModeLayoutId;
        mExtraAttrs = p.mExtraAttrs;
        mOverlayMonitor = p.mOverlayMonitor;
        devicePaddings = p.devicePaddings;
    }

@@ -215,7 +198,6 @@ public class InvariantDeviceProfile {
                        onConfigChanged(displayContext);
                    }
                });
        mOverlayMonitor = new OverlayMonitor(context);
    }

    /**
@@ -266,17 +248,6 @@ public class InvariantDeviceProfile {
                ? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null;
    }

    /**
     * Retrieve system defined or RRO overriden icon shape.
     */
    private static String getIconShapePath(Context context) {
        if (CONFIG_ICON_MASK_RES_ID == 0) {
            Log.e(TAG, "Icon mask res identifier failed to retrieve.");
            return "";
        }
        return context.getResources().getString(CONFIG_ICON_MASK_RES_ID);
    }

    private String initGrid(Context context, String gridName) {
        Info displayInfo = DisplayController.INSTANCE.get(context).getInfo();
        // Determine if we have split display
@@ -317,7 +288,6 @@ public class InvariantDeviceProfile {
        mExtraAttrs = closestProfile.extraAttrs;

        iconSize = displayOption.iconSize;
        iconShapePath = getIconShapePath(context);
        landscapeIconSize = displayOption.landscapeIconSize;
        iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
        iconTextSize = displayOption.iconTextSize;
@@ -391,18 +361,6 @@ public class InvariantDeviceProfile {
        mChangeListeners.remove(listener);
    }

    public void verifyConfigChangedInBackground(final Context context) {
        String savedIconMaskPath = getDevicePrefs(context).getString(KEY_ICON_PATH_REF, "");
        // Good place to check if grid size changed in themepicker when launcher was dead.
        if (savedIconMaskPath.isEmpty()) {
            getDevicePrefs(context).edit().putString(KEY_ICON_PATH_REF, getIconShapePath(context))
                    .apply();
        } else if (!savedIconMaskPath.equals(getIconShapePath(context))) {
            getDevicePrefs(context).edit().putString(KEY_ICON_PATH_REF, getIconShapePath(context))
                    .apply();
            apply(CHANGE_FLAG_ICON_PARAMS);
        }
    }

    public void setCurrentGrid(Context context, String gridName) {
        Context appContext = context.getApplicationContext();
@@ -414,36 +372,13 @@ public class InvariantDeviceProfile {
        if (TestProtocol.sDebugTracing) {
            Log.d(TestProtocol.LAUNCHER_NOT_TRANSPOSED, "IDP.onConfigChanged");
        }
        // Config changes, what shall we do?
        InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);

        // Re-init grid
        String gridName = getCurrentGridName(context);
        initGrid(context, gridName);

        int changeFlags = 0;
        if (numRows != oldProfile.numRows ||
                numColumns != oldProfile.numColumns ||
                numFolderColumns != oldProfile.numFolderColumns ||
                numFolderRows != oldProfile.numFolderRows ||
                numDatabaseHotseatIcons != oldProfile.numDatabaseHotseatIcons) {
            changeFlags |= CHANGE_FLAG_GRID;
        }

        if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize ||
                !iconShapePath.equals(oldProfile.iconShapePath)) {
            changeFlags |= CHANGE_FLAG_ICON_PARAMS;
        }
        if (!iconShapePath.equals(oldProfile.iconShapePath)) {
            IconShape.init(context);
        }

        apply(changeFlags);
    }

    private void apply(int changeFlags) {
        for (OnIDPChangeListener listener : mChangeListeners) {
            listener.onIdpChanged(changeFlags, this);
            listener.onIdpChanged(this);
        }
    }

@@ -650,7 +585,10 @@ public class InvariantDeviceProfile {

    public interface OnIDPChangeListener {

        void onIdpChanged(int changeFlags, InvariantDeviceProfile profile);
        /**
         * Called when the device provide changes
         */
        void onIdpChanged(InvariantDeviceProfile profile);
    }


@@ -809,18 +747,4 @@ public class InvariantDeviceProfile {
            return this;
        }
    }

    private class OverlayMonitor extends BroadcastReceiver {

        private final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";

        OverlayMonitor(Context context) {
            context.registerReceiver(this, getPackageFilter("android", ACTION_OVERLAY_CHANGED));
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            onConfigChanged(context);
        }
    }
}
Loading