From c55a350da84f14fff530b95c99f89890e450a79b Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Tue, 4 Dec 2018 15:43:16 -0800 Subject: 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 --- .../android/launcher3/InvariantDeviceProfile.java | 61 ++++++++++++++++++---- src/com/android/launcher3/LauncherAppState.java | 6 ++- src/com/android/launcher3/config/BaseFlags.java | 2 +- src/com/android/launcher3/util/ConfigMonitor.java | 19 ++++++- 4 files changed, 73 insertions(+), 15 deletions(-) (limited to 'src/com/android/launcher3') diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index dbefa4518..5c842a57d 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -17,10 +17,12 @@ package com.android.launcher3; import static com.android.launcher3.config.FeatureFlags.APPLY_CONFIG_AT_RUNTIME; +import static com.android.launcher3.Utilities.getDevicePrefs; import android.annotation.TargetApi; import android.content.Context; import android.content.res.Configuration; +import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Point; @@ -46,24 +48,30 @@ import androidx.annotation.VisibleForTesting; 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. public static final MainThreadInitializedObject INSTANCE = 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; 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 // buckets. - private static float KNEARESTNEIGHBOR = 3; - private static float WEIGHT_POWER = 5; + private static final float KNEARESTNEIGHBOR = 3; + private static final float WEIGHT_POWER = 5; // 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. @@ -77,6 +85,7 @@ public class InvariantDeviceProfile { public int numFolderRows; public int numFolderColumns; public float iconSize; + public String iconShapePath; public float landscapeIconSize; public int iconBitmapSize; public int fillResIconDpi; @@ -107,6 +116,7 @@ public class InvariantDeviceProfile { numFolderRows = p.numFolderRows; numFolderColumns = p.numFolderColumns; iconSize = p.iconSize; + iconShapePath = p.iconShapePath; landscapeIconSize = p.landscapeIconSize; iconTextSize = p.iconTextSize; numHotseatIcons = p.numHotseatIcons; @@ -116,11 +126,22 @@ public class InvariantDeviceProfile { @TargetApi(23) 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, 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) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = wm.getDefaultDisplay(); @@ -152,10 +173,11 @@ public class InvariantDeviceProfile { numFolderColumns = closestProfile.numFolderColumns; if (!closestProfile.name.equals(gridName)) { Utilities.getPrefs(context).edit() - .putString(KEY_IDP_GRIP_NAME, closestProfile.name).apply(); + .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply(); } iconSize = interpolatedDisplayOption.iconSize; + iconShapePath = getIconShapePath(context); landscapeIconSize = interpolatedDisplayOption.landscapeIconSize; iconBitmapSize = Utilities.pxFromDp(iconSize, dm); iconTextSize = interpolatedDisplayOption.iconTextSize; @@ -197,12 +219,26 @@ public class InvariantDeviceProfile { 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) { // Config changes, what shall we do? InvariantDeviceProfile oldProfile = new InvariantDeviceProfile(this); // 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; if (numRows != oldProfile.numRows || @@ -213,10 +249,14 @@ public class InvariantDeviceProfile { changeFlags |= CHANGE_FLAG_GRID; } - if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize) { - changeFlags |= CHANGE_FLAG_ICON_SIZE; + if (iconSize != oldProfile.iconSize || iconBitmapSize != oldProfile.iconBitmapSize || + !iconShapePath.equals(oldProfile.iconShapePath)) { + changeFlags |= CHANGE_FLAG_ICON_PARAMS; } + apply(context, changeFlags); + } + private void apply(Context context, int changeFlags) { // Create a new config monitor mConfigMonitor.unregister(); mConfigMonitor = new ConfigMonitor(context, this::onConfigChanged); @@ -231,7 +271,6 @@ public class InvariantDeviceProfile { try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) { final int depth = parser.getDepth(); int type; - while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { if ((type == XmlPullParser.START_TAG) && "grid-option".equals(parser.getName())) { diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 182a4ee1f..74fa447d1 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -16,14 +16,15 @@ 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.InvariantDeviceProfile.CHANGE_FLAG_ICON_SIZE; import android.content.ComponentName; import android.content.ContentProviderClient; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.Handler; import android.util.Log; import com.android.launcher3.compat.LauncherAppsCompat; @@ -97,6 +98,7 @@ public class LauncherAppState { mContext.registerReceiver(mModel, filter); UserManagerCompat.getInstance(mContext).enableAndResetCache(); mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged); + new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context)); if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) { mNotificationDotsObserver = null; @@ -121,7 +123,7 @@ public class LauncherAppState { return; } - if ((changeFlags & CHANGE_FLAG_ICON_SIZE) != 0) { + if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) != 0) { LauncherIcons.clearPool(); mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize); } diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java index 3a7c949a6..449cde76f 100644 --- a/src/com/android/launcher3/config/BaseFlags.java +++ b/src/com/android/launcher3/config/BaseFlags.java @@ -93,7 +93,7 @@ abstract class BaseFlags { * Feature flag to handle define config changes dynamically instead of killing the process. */ 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( "ENABLE_TASK_STABILIZER", false, "Stable task list across fast task switches"); diff --git a/src/com/android/launcher3/util/ConfigMonitor.java b/src/com/android/launcher3/util/ConfigMonitor.java index 717acdccb..607afabef 100644 --- a/src/com/android/launcher3/util/ConfigMonitor.java +++ b/src/com/android/launcher3/util/ConfigMonitor.java @@ -29,6 +29,7 @@ import android.util.Log; import android.view.Display; import android.view.WindowManager; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.Utilities.Consumer; @@ -40,6 +41,8 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener 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 mTmpPoint2 = new Point(); @@ -72,7 +75,15 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener mCallback = callback; + // Listen for configuration change 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) .registerDisplayListener(this, new Handler(UiThreadHelper.getBackgroundLooper())); } @@ -80,8 +91,14 @@ public class ConfigMonitor extends BroadcastReceiver implements DisplayListener @Override public void onReceive(Context context, Intent intent) { 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) { - Log.d(TAG, "Configuration changed"); + Log.d(TAG, "Configuration changed."); notifyChange(); } } -- cgit v1.2.3