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

Commit c55a350d authored by Hyunyoung Song's avatar Hyunyoung Song
Browse files

Refresh icon cache when icon shape path has changed

Bug: 120505990

$ adb shell cmd overlay enable --user 0 com.android.theme.icon.roundedrect
$ adb shell cmd overlay disable --user 0 com.android.theme.icon.roundedrect
$ adb shell cmd overlay enable --user 0 com.android.theme.icon.teardrop
$ adb shell cmd overlay disable --user 0 com.android.theme.icon.teardrop

Change-Id: I06663b9727f7434aae737d39977f1e6cf09bffbf
parent e018711a
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -151,7 +151,7 @@ public abstract class BaseIconCache {
    private synchronized void updateIconParamsBg(int iconDpi, int iconPixelSize) {
    private synchronized void updateIconParamsBg(int iconDpi, int iconPixelSize) {
        mIconDpi = iconDpi;
        mIconDpi = iconDpi;
        mDefaultIcons.clear();
        mDefaultIcons.clear();

        mIconDb.clear();
        mIconDb.close();
        mIconDb.close();
        mIconDb = new IconDB(mContext, mDbFileName, iconPixelSize);
        mIconDb = new IconDB(mContext, mDbFileName, iconPixelSize);
        mCache.clear();
        mCache.clear();
+50 −11
Original line number Original line Diff line number Diff line
@@ -17,10 +17,12 @@
package com.android.launcher3;
package com.android.launcher3;


import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME;
import static com.android.launcher3.Utilities.getDevicePrefs;


import android.annotation.TargetApi;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.content.res.XmlResourceParser;
import android.graphics.Point;
import android.graphics.Point;
@@ -46,24 +48,30 @@ import androidx.annotation.VisibleForTesting;


public class InvariantDeviceProfile {
public class InvariantDeviceProfile {


    public static final String TAG = "IDP";
    // We do not need any synchronization for this variable as its only written on UI thread.
    // We do not need any synchronization for this variable as its only written on UI thread.
    public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
    public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
            new MainThreadInitializedObject<>(InvariantDeviceProfile::new);
            new MainThreadInitializedObject<>(InvariantDeviceProfile::new);


    private static final String KEY_IDP_GRIP_NAME = "idp_grid_name";
    private static final String KEY_IDP_GRID_NAME = "idp_grid_name";


    private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
    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_GRID = 1 << 0;
    public static final int CHANGE_FLAG_ICON_SIZE = 1 << 1;
    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
    // Constants that affects the interpolation curve between statically defined device profile
    // buckets.
    // buckets.
    private static float KNEARESTNEIGHBOR = 3;
    private static final float KNEARESTNEIGHBOR = 3;
    private static float WEIGHT_POWER = 5;
    private static final float WEIGHT_POWER = 5;


    // used to offset float not being able to express extremely small weights in extreme cases.
    // used to offset float not being able to express extremely small weights in extreme cases.
    private static float WEIGHT_EFFICIENT = 100000f;
    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.
     * Number of icons per row and column in the workspace.
@@ -77,6 +85,7 @@ public class InvariantDeviceProfile {
    public int numFolderRows;
    public int numFolderRows;
    public int numFolderColumns;
    public int numFolderColumns;
    public float iconSize;
    public float iconSize;
    public String iconShapePath;
    public float landscapeIconSize;
    public float landscapeIconSize;
    public int iconBitmapSize;
    public int iconBitmapSize;
    public int fillResIconDpi;
    public int fillResIconDpi;
@@ -107,6 +116,7 @@ public class InvariantDeviceProfile {
        numFolderRows = p.numFolderRows;
        numFolderRows = p.numFolderRows;
        numFolderColumns = p.numFolderColumns;
        numFolderColumns = p.numFolderColumns;
        iconSize = p.iconSize;
        iconSize = p.iconSize;
        iconShapePath = p.iconShapePath;
        landscapeIconSize = p.landscapeIconSize;
        landscapeIconSize = p.landscapeIconSize;
        iconTextSize = p.iconTextSize;
        iconTextSize = p.iconTextSize;
        numHotseatIcons = p.numHotseatIcons;
        numHotseatIcons = p.numHotseatIcons;
@@ -116,11 +126,22 @@ public class InvariantDeviceProfile {


    @TargetApi(23)
    @TargetApi(23)
    private InvariantDeviceProfile(Context context) {
    private InvariantDeviceProfile(Context context) {
        initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRIP_NAME, null));
        initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));
        mConfigMonitor = new ConfigMonitor(context,
        mConfigMonitor = new ConfigMonitor(context,
                APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
                APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
    }
    }


    /**
     * 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 void initGrid(Context context, String gridName) {
    private void initGrid(Context context, String gridName) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Display display = wm.getDefaultDisplay();
@@ -152,10 +173,11 @@ public class InvariantDeviceProfile {
        numFolderColumns = closestProfile.numFolderColumns;
        numFolderColumns = closestProfile.numFolderColumns;
        if (!closestProfile.name.equals(gridName)) {
        if (!closestProfile.name.equals(gridName)) {
            Utilities.getPrefs(context).edit()
            Utilities.getPrefs(context).edit()
                    .putString(KEY_IDP_GRIP_NAME, closestProfile.name).apply();
                    .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
        }
        }


        iconSize = interpolatedDisplayOption.iconSize;
        iconSize = interpolatedDisplayOption.iconSize;
        iconShapePath = getIconShapePath(context);
        landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
        landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
        iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
        iconBitmapSize = Utilities.pxFromDp(iconSize, dm);
        iconTextSize = interpolatedDisplayOption.iconTextSize;
        iconTextSize = interpolatedDisplayOption.iconTextSize;
@@ -197,12 +219,26 @@ public class InvariantDeviceProfile {
        android.os.Process.killProcess(android.os.Process.myPid());
        android.os.Process.killProcess(android.os.Process.myPid());
    }
    }


    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(context, CHANGE_FLAG_ICON_PARAMS);
        }
    }

    private void onConfigChanged(Context context) {
    private void onConfigChanged(Context context) {
        // Config changes, what shall we do?
        // Config changes, what shall we do?
        InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);
        InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this);


        // Re-init grid
        // Re-init grid
        initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRIP_NAME, null));
        initGrid(context, Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null));


        int changeFlags = 0;
        int changeFlags = 0;
        if (numRows != oldProfile.numRows ||
        if (numRows != oldProfile.numRows ||
@@ -213,10 +249,14 @@ public class InvariantDeviceProfile {
            changeFlags |= CHANGE_FLAG_GRID;
            changeFlags |= CHANGE_FLAG_GRID;
        }
        }


        if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize) {
        if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize ||
            changeFlags |= CHANGE_FLAG_ICON_SIZE;
                !iconShapePath.equals(oldProfile.iconShapePath)) {
            changeFlags |= CHANGE_FLAG_ICON_PARAMS;
        }
        apply(context, changeFlags);
    }
    }


    private void apply(Context context, int changeFlags) {
        // Create a new config monitor
        // Create a new config monitor
        mConfigMonitor.unregister();
        mConfigMonitor.unregister();
        mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
        mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged);
@@ -231,7 +271,6 @@ public class InvariantDeviceProfile {
        try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
        try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
            final int depth = parser.getDepth();
            final int depth = parser.getDepth();
            int type;
            int type;

            while (((type = parser.next()) != XmlPullParser.END_TAG ||
            while (((type = parser.next()) != XmlPullParser.END_TAG ||
                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                    parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
                if ((type == XmlPullParser.START_TAG) && "grid-option".equals(parser.getName())) {
                if ((type == XmlPullParser.START_TAG) && "grid-option".equals(parser.getName())) {
+4 −2
Original line number Original line Diff line number Diff line
@@ -16,14 +16,15 @@


package com.android.launcher3;
package com.android.launcher3;


import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_SIZE;


import android.content.ComponentName;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
import android.os.Handler;
import android.util.Log;
import android.util.Log;


import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -97,6 +98,7 @@ public class LauncherAppState {
        mContext.registerReceiver(mModel, filter);
        mContext.registerReceiver(mModel, filter);
        UserManagerCompat.getInstance(mContext).enableAndResetCache();
        UserManagerCompat.getInstance(mContext).enableAndResetCache();
        mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged);
        mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged);
        new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context));


        if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) {
        if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) {
            mNotificationDotsObserver = null;
            mNotificationDotsObserver = null;
@@ -121,7 +123,7 @@ public class LauncherAppState {
            return;
            return;
        }
        }


        if ((changeFlags & CHANGE_FLAG_ICON_SIZE) != 0) {
        if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) != 0) {
            LauncherIcons.clearPool();
            LauncherIcons.clearPool();
            mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize);
            mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize);
        }
        }
+1 −1
Original line number Original line Diff line number Diff line
@@ -93,7 +93,7 @@ abstract class BaseFlags {
     * Feature flag to handle define config changes dynamically instead of killing the process.
     * Feature flag to handle define config changes dynamically instead of killing the process.
     */
     */
    public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
    public static final TogglableFlag APPLY_CONFIG_AT_RUNTIME = new TogglableFlag(
            "APPLY_CONFIG_AT_RUNTIME", false, "Apply display changes dynamically");
            "APPLY_CONFIG_AT_RUNTIME", true, "Apply display changes dynamically");


    public static final TogglableFlag ENABLE_TASK_STABILIZER = new TogglableFlag(
    public static final TogglableFlag ENABLE_TASK_STABILIZER = new TogglableFlag(
            "ENABLE_TASK_STABILIZER", false, "Stable task list across fast task switches");
            "ENABLE_TASK_STABILIZER", false, "Stable task list across fast task switches");
+18 −1
Original line number Original line Diff line number Diff line
@@ -29,6 +29,7 @@ import android.util.Log;
import android.view.Display;
import android.view.Display;
import android.view.WindowManager;
import android.view.WindowManager;


import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.Utilities.Consumer;
import com.android.launcher3.Utilities.Consumer;


@@ -40,6 +41,8 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener


    private static final String TAG = "ConfigMonitor";
    private static final String TAG = "ConfigMonitor";


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

    private final Point mTmpPoint1 = new Point();
    private final Point mTmpPoint1 = new Point();
    private final Point mTmpPoint2 = new Point();
    private final Point mTmpPoint2 = new Point();


@@ -72,7 +75,15 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener


        mCallback = callback;
        mCallback = callback;


        // Listen for configuration change
        mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));
        mContext.registerReceiver(this, new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED));

        // Listen for {@link OverlayManager} change
        IntentFilter filter = new IntentFilter(ACTION_OVERLAY_CHANGED);
        filter.addDataScheme("package");
        mContext.registerReceiver(this, filter);

        // Listen for display manager change
        mContext.getSystemService(DisplayManager.class)
        mContext.getSystemService(DisplayManager.class)
                .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
                .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper()));
    }
    }
@@ -80,8 +91,14 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener
    @Override
    @Override
    public void onReceive(Context context, Intent intent) {
    public void onReceive(Context context, Intent intent) {
        Configuration config = context.getResources().getConfiguration();
        Configuration config = context.getResources().getConfiguration();
        // TODO: when overlay manager service encodes more information to the Uri such as category
        // of the overlay, only listen to the ones that are of interest to launcher.
        if (intent != null && ACTION_OVERLAY_CHANGED.equals(intent.getAction())) {
            Log.d(TAG, "Overlay changed.");
            notifyChange();
        }
        if (mFontScale != config.fontScale || mDensity != config.densityDpi) {
        if (mFontScale != config.fontScale || mDensity != config.densityDpi) {
            Log.d(TAG, "Configuration changed");
            Log.d(TAG, "Configuration changed.");
            notifyChange();
            notifyChange();
        }
        }
    }
    }