Loading core/java/android/provider/Settings.java +25 −0 Original line number Diff line number Diff line Loading @@ -7785,6 +7785,31 @@ public final class Settings { */ public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants"; /** * ShortcutManager specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * "reset_interval_sec=86400,max_daily_updates=5" * * The following keys are supported: * * <pre> * reset_interval_sec (long) * max_daily_updates (int) * max_icon_dimension_dp (int, DP) * max_icon_dimension_dp_lowram (int, DP) * max_shortcuts (int) * icon_quality (int, 0-100) * icon_format (String) * </pre> * * <p> * Type: string * @hide * @see com.android.server.pm.ShortcutService.ConfigConstants */ public static final String SHORTCUT_MANAGER_CONSTANTS = "shortcut_manager_constants"; /** * Get the key that retrieves a bluetooth headset's priority. * @hide Loading services/core/java/com/android/server/pm/ShortcutService.java +186 −34 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.text.format.Time; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.KeyValueListParser; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; Loading Loading @@ -92,8 +93,6 @@ import java.util.function.Predicate; /** * TODO: * * - Implement launchShortcut * * - Detect when already registered instances are passed to APIs again, which might break * internal bitmap handling. * Loading @@ -103,8 +102,6 @@ import java.util.function.Predicate; * * - Pinned per each launcher package (multiple launchers) * * - Load config from settings * * - Make save async (should we?) * * - Scan and remove orphan bitmaps (just in case). Loading @@ -117,11 +114,26 @@ public class ShortcutService extends IShortcutService.Stub { private static final boolean DEBUG = true; // STOPSHIP if true private static final boolean DEBUG_LOAD = true; // STOPSHIP if true private static final int DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day private static final int DEFAULT_MAX_DAILY_UPDATES = 10; private static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5; private static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; private static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48; @VisibleForTesting static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day @VisibleForTesting static final int DEFAULT_MAX_DAILY_UPDATES = 10; @VisibleForTesting static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5; @VisibleForTesting static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; @VisibleForTesting static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48; @VisibleForTesting static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name(); @VisibleForTesting static final int DEFAULT_ICON_PERSIST_QUALITY = 100; private static final int SAVE_DELAY_MS = 5000; // in milliseconds. Loading Loading @@ -158,6 +170,44 @@ public class ShortcutService extends IShortcutService.Stub { private static final String ATTR_ICON_RES = "icon-res"; private static final String ATTR_BITMAP_PATH = "bitmap-path"; @VisibleForTesting interface ConfigConstants { /** * Key name for the throttling reset interval, in seconds. (long) */ String KEY_RESET_INTERVAL_SEC = "reset_interval_sec"; /** * Key name for the max number of modifying API calls per app for every interval. (int) */ String KEY_MAX_DAILY_UPDATES = "max_daily_updates"; /** * Key name for the max icon dimensions in DP, for non-low-memory devices. */ String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp"; /** * Key name for the max icon dimensions in DP, for low-memory devices. */ String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram"; /** * Key name for the max dynamic shortcuts per app. (int) */ String KEY_MAX_SHORTCUTS = "max_shortcuts"; /** * Key name for icom compression quality, 0-100. */ String KEY_ICON_QUALITY = "icon_quality"; /** * Key name for icon compression format: "PNG", "JPEG" or "WEBP" */ String KEY_ICON_FORMAT = "icon_format"; } private final Context mContext; private final Object mLock = new Object(); Loading Loading @@ -416,9 +466,8 @@ public class ShortcutService extends IShortcutService.Stub { */ private int mMaxIconDimension; private CompressFormat mIconPersistFormat = CompressFormat.PNG; private int mIconPersistQuality = 100; private CompressFormat mIconPersistFormat; private int mIconPersistQuality; public ShortcutService(Context context) { mContext = Preconditions.checkNotNull(context); Loading Loading @@ -498,22 +547,75 @@ public class ShortcutService extends IShortcutService.Stub { */ private void initialize() { synchronized (mLock) { injectLoadConfigurationLocked(); loadConfigurationLocked(); loadBaseStateLocked(); } } // Test overrides it to inject different values. /** * Load the configuration from Settings. */ private void loadConfigurationLocked() { updateConfigurationLocked(injectShortcutManagerConstants()); } /** * Load the configuration from Settings. */ @VisibleForTesting void injectLoadConfigurationLocked() { mResetInterval = DEFAULT_RESET_INTERVAL_SEC * 1000L; mMaxDailyUpdates = DEFAULT_MAX_DAILY_UPDATES; mMaxDynamicShortcuts = DEFAULT_MAX_SHORTCUTS_PER_APP; final int iconDimensionDp = (injectIsLowRamDevice() ? DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP : DEFAULT_MAX_ICON_DIMENSION_DP); mMaxIconDimension = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, iconDimensionDp, boolean updateConfigurationLocked(String config) { boolean result = true; final KeyValueListParser parser = new KeyValueListParser(','); try { parser.setString(config); } catch (IllegalArgumentException e) { // Failed to parse the settings string, log this and move on // with defaults. Slog.e(TAG, "Bad shortcut manager settings", e); result = false; } mResetInterval = parser.getLong( ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC) * 1000L; mMaxDailyUpdates = (int) parser.getLong( ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES); mMaxDynamicShortcuts = (int) parser.getLong( ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP); final int iconDimensionDp = injectIsLowRamDevice() ? (int) parser.getLong( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM, DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP) : (int) parser.getLong( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP, DEFAULT_MAX_ICON_DIMENSION_DP); mMaxIconDimension = injectDipToPixel(iconDimensionDp); mIconPersistFormat = CompressFormat.valueOf( parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT)); mIconPersistQuality = (int) parser.getLong( ConfigConstants.KEY_ICON_QUALITY, DEFAULT_ICON_PERSIST_QUALITY); return result; } @VisibleForTesting String injectShortcutManagerConstants() { return android.provider.Settings.Global.getString( mContext.getContentResolver(), android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS); } @VisibleForTesting int injectDipToPixel(int dip) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, mContext.getResources().getDisplayMetrics()); } Loading Loading @@ -1829,14 +1931,27 @@ public class ShortcutService extends IShortcutService.Stub { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); int ret = 1; switch (cmd) { case "reset-package-throttling": return handleResetPackageThrottling(); ret = handleResetPackageThrottling(); break; case "reset-throttling": return handleResetThrottling(); ret = handleResetThrottling(); break; case "override-config": ret = handleOverrideConfig(); break; case "reset-config": ret = handleResetConfig(); break; default: return handleDefaultCommands(cmd); } if (ret == 0) { pw.println("Success"); } return ret; } @Override Loading @@ -1850,6 +1965,12 @@ public class ShortcutService extends IShortcutService.Stub { pw.println("cmd shortcut reset-throttling"); pw.println(" Reset throttling for all packages and users"); pw.println(); pw.println("cmd shortcut override-config CONFIG"); pw.println(" Override the configuration for testing (will last until reboot)"); pw.println(); pw.println("cmd shortcut reset-config"); pw.println(" Reset the configuration set with \"update-config\""); pw.println(); } private int handleResetThrottling() { Loading Loading @@ -1881,6 +2002,26 @@ public class ShortcutService extends IShortcutService.Stub { return 0; } private int handleOverrideConfig() { final PrintWriter pw = getOutPrintWriter(); final String config = getNextArgRequired(); synchronized (mLock) { if (!updateConfigurationLocked(config)) { pw.println("override-config failed. See logcat for details."); return 1; } } return 0; } private int handleResetConfig() { synchronized (mLock) { loadConfigurationLocked(); } return 0; } } // === Unit test support === Loading @@ -1903,6 +2044,7 @@ public class ShortcutService extends IShortcutService.Stub { return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER); } @VisibleForTesting boolean injectIsLowRamDevice() { return ActivityManager.isLowRamDeviceStatic(); } Loading @@ -1917,22 +2059,32 @@ public class ShortcutService extends IShortcutService.Stub { } @VisibleForTesting void setMaxDynamicShortcutsForTest(int max) { mMaxDynamicShortcuts = max; int getMaxDynamicShortcutsForTest() { return mMaxDynamicShortcuts; } @VisibleForTesting void setMaxDailyUpdatesForTest(int max) { mMaxDailyUpdates = max; int getMaxDailyUpdatesForTest() { return mMaxDailyUpdates; } @VisibleForTesting long getResetIntervalForTest() { return mResetInterval; } @VisibleForTesting int getMaxIconDimensionForTest() { return mMaxIconDimension; } @VisibleForTesting void setMaxIconDimensionForTest(int dimension) { mMaxIconDimension = dimension; CompressFormat getIconPersistFormatForTest() { return mIconPersistFormat; } @VisibleForTesting public void setResetIntervalForTest(long interval) { mResetInterval = interval; int getIconPersistQualityForTest() { return mIconPersistQuality; } } services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +63 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.pm.ShortcutManager; import android.content.pm.ShortcutServiceInternal; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.drawable.Icon; import android.os.Bundle; Loading @@ -42,6 +43,7 @@ import com.android.frameworks.servicestests.R; import com.android.internal.util.Preconditions; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ShortcutService.ConfigConstants; import com.android.server.pm.ShortcutService.FileOutputStreamWithPath; import libcore.io.IoUtils; Loading Loading @@ -114,11 +116,20 @@ public class ShortcutManagerTest extends AndroidTestCase { } @Override void injectLoadConfigurationLocked() { setResetIntervalForTest(INTERVAL); setMaxDynamicShortcutsForTest(MAX_SHORTCUTS); setMaxDailyUpdatesForTest(MAX_DAILY_UPDATES); setMaxIconDimensionForTest(MAX_ICON_DIMENSION); String injectShortcutManagerConstants() { return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + "," + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + "," + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=" + MAX_DAILY_UPDATES + "," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + "," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=" + MAX_ICON_DIMENSION_LOWRAM + "," + ConfigConstants.KEY_ICON_FORMAT + "=PNG," + ConfigConstants.KEY_ICON_QUALITY + "=100"; } @Override int injectDipToPixel(int dip) { return dip; } @Override Loading Loading @@ -151,6 +162,11 @@ public class ShortcutManagerTest extends AndroidTestCase { void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) { // Can't check } @Override boolean injectIsLowRamDevice() { return mInjectdIsLowRamDevice; } } /** ShortcutManager with injection override methods. */ Loading Loading @@ -186,6 +202,8 @@ public class ShortcutManagerTest extends AndroidTestCase { private long mInjectedCurrentTimeLillis; private boolean mInjectdIsLowRamDevice; private int mInjectedCallingUid; private String mInjectedClientPackage; Loading Loading @@ -216,6 +234,8 @@ public class ShortcutManagerTest extends AndroidTestCase { private static final int MAX_ICON_DIMENSION = 128; private static final int MAX_ICON_DIMENSION_LOWRAM = 32; @Override protected void setUp() throws Exception { super.setUp(); Loading Loading @@ -676,6 +696,44 @@ public class ShortcutManagerTest extends AndroidTestCase { // TODO Add various broken cases. } public void testLoadConfig() { mService.updateConfigurationLocked( ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123," + ConfigConstants.KEY_MAX_SHORTCUTS + "=4," + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=5," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50," + ConfigConstants.KEY_ICON_FORMAT + "=WEBP," + ConfigConstants.KEY_ICON_QUALITY + "=75"); assertEquals(123000, mService.getResetIntervalForTest()); assertEquals(4, mService.getMaxDynamicShortcutsForTest()); assertEquals(5, mService.getMaxDailyUpdatesForTest()); assertEquals(100, mService.getMaxIconDimensionForTest()); assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest()); assertEquals(75, mService.getIconPersistQualityForTest()); mInjectdIsLowRamDevice = true; mService.updateConfigurationLocked( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50," + ConfigConstants.KEY_ICON_FORMAT + "=JPEG"); assertEquals(ShortcutService.DEFAULT_RESET_INTERVAL_SEC * 1000, mService.getResetIntervalForTest()); assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP, mService.getMaxDynamicShortcutsForTest()); assertEquals(ShortcutService.DEFAULT_MAX_DAILY_UPDATES, mService.getMaxDailyUpdatesForTest()); assertEquals(50, mService.getMaxIconDimensionForTest()); assertEquals(CompressFormat.JPEG, mService.getIconPersistFormatForTest()); assertEquals(ShortcutService.DEFAULT_ICON_PERSIST_QUALITY, mService.getIconPersistQualityForTest()); } // === Test for app side APIs === /** Test for {@link android.content.pm.ShortcutManager#getMaxDynamicShortcutCount()} */ Loading Loading
core/java/android/provider/Settings.java +25 −0 Original line number Diff line number Diff line Loading @@ -7785,6 +7785,31 @@ public final class Settings { */ public static final String ALARM_MANAGER_CONSTANTS = "alarm_manager_constants"; /** * ShortcutManager specific settings. * This is encoded as a key=value list, separated by commas. Ex: * * "reset_interval_sec=86400,max_daily_updates=5" * * The following keys are supported: * * <pre> * reset_interval_sec (long) * max_daily_updates (int) * max_icon_dimension_dp (int, DP) * max_icon_dimension_dp_lowram (int, DP) * max_shortcuts (int) * icon_quality (int, 0-100) * icon_format (String) * </pre> * * <p> * Type: string * @hide * @see com.android.server.pm.ShortcutService.ConfigConstants */ public static final String SHORTCUT_MANAGER_CONSTANTS = "shortcut_manager_constants"; /** * Get the key that retrieves a bluetooth headset's priority. * @hide Loading
services/core/java/com/android/server/pm/ShortcutService.java +186 −34 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.text.format.Time; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.KeyValueListParser; import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; Loading Loading @@ -92,8 +93,6 @@ import java.util.function.Predicate; /** * TODO: * * - Implement launchShortcut * * - Detect when already registered instances are passed to APIs again, which might break * internal bitmap handling. * Loading @@ -103,8 +102,6 @@ import java.util.function.Predicate; * * - Pinned per each launcher package (multiple launchers) * * - Load config from settings * * - Make save async (should we?) * * - Scan and remove orphan bitmaps (just in case). Loading @@ -117,11 +114,26 @@ public class ShortcutService extends IShortcutService.Stub { private static final boolean DEBUG = true; // STOPSHIP if true private static final boolean DEBUG_LOAD = true; // STOPSHIP if true private static final int DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day private static final int DEFAULT_MAX_DAILY_UPDATES = 10; private static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5; private static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; private static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48; @VisibleForTesting static final long DEFAULT_RESET_INTERVAL_SEC = 24 * 60 * 60; // 1 day @VisibleForTesting static final int DEFAULT_MAX_DAILY_UPDATES = 10; @VisibleForTesting static final int DEFAULT_MAX_SHORTCUTS_PER_APP = 5; @VisibleForTesting static final int DEFAULT_MAX_ICON_DIMENSION_DP = 96; @VisibleForTesting static final int DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP = 48; @VisibleForTesting static final String DEFAULT_ICON_PERSIST_FORMAT = CompressFormat.PNG.name(); @VisibleForTesting static final int DEFAULT_ICON_PERSIST_QUALITY = 100; private static final int SAVE_DELAY_MS = 5000; // in milliseconds. Loading Loading @@ -158,6 +170,44 @@ public class ShortcutService extends IShortcutService.Stub { private static final String ATTR_ICON_RES = "icon-res"; private static final String ATTR_BITMAP_PATH = "bitmap-path"; @VisibleForTesting interface ConfigConstants { /** * Key name for the throttling reset interval, in seconds. (long) */ String KEY_RESET_INTERVAL_SEC = "reset_interval_sec"; /** * Key name for the max number of modifying API calls per app for every interval. (int) */ String KEY_MAX_DAILY_UPDATES = "max_daily_updates"; /** * Key name for the max icon dimensions in DP, for non-low-memory devices. */ String KEY_MAX_ICON_DIMENSION_DP = "max_icon_dimension_dp"; /** * Key name for the max icon dimensions in DP, for low-memory devices. */ String KEY_MAX_ICON_DIMENSION_DP_LOWRAM = "max_icon_dimension_dp_lowram"; /** * Key name for the max dynamic shortcuts per app. (int) */ String KEY_MAX_SHORTCUTS = "max_shortcuts"; /** * Key name for icom compression quality, 0-100. */ String KEY_ICON_QUALITY = "icon_quality"; /** * Key name for icon compression format: "PNG", "JPEG" or "WEBP" */ String KEY_ICON_FORMAT = "icon_format"; } private final Context mContext; private final Object mLock = new Object(); Loading Loading @@ -416,9 +466,8 @@ public class ShortcutService extends IShortcutService.Stub { */ private int mMaxIconDimension; private CompressFormat mIconPersistFormat = CompressFormat.PNG; private int mIconPersistQuality = 100; private CompressFormat mIconPersistFormat; private int mIconPersistQuality; public ShortcutService(Context context) { mContext = Preconditions.checkNotNull(context); Loading Loading @@ -498,22 +547,75 @@ public class ShortcutService extends IShortcutService.Stub { */ private void initialize() { synchronized (mLock) { injectLoadConfigurationLocked(); loadConfigurationLocked(); loadBaseStateLocked(); } } // Test overrides it to inject different values. /** * Load the configuration from Settings. */ private void loadConfigurationLocked() { updateConfigurationLocked(injectShortcutManagerConstants()); } /** * Load the configuration from Settings. */ @VisibleForTesting void injectLoadConfigurationLocked() { mResetInterval = DEFAULT_RESET_INTERVAL_SEC * 1000L; mMaxDailyUpdates = DEFAULT_MAX_DAILY_UPDATES; mMaxDynamicShortcuts = DEFAULT_MAX_SHORTCUTS_PER_APP; final int iconDimensionDp = (injectIsLowRamDevice() ? DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP : DEFAULT_MAX_ICON_DIMENSION_DP); mMaxIconDimension = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, iconDimensionDp, boolean updateConfigurationLocked(String config) { boolean result = true; final KeyValueListParser parser = new KeyValueListParser(','); try { parser.setString(config); } catch (IllegalArgumentException e) { // Failed to parse the settings string, log this and move on // with defaults. Slog.e(TAG, "Bad shortcut manager settings", e); result = false; } mResetInterval = parser.getLong( ConfigConstants.KEY_RESET_INTERVAL_SEC, DEFAULT_RESET_INTERVAL_SEC) * 1000L; mMaxDailyUpdates = (int) parser.getLong( ConfigConstants.KEY_MAX_DAILY_UPDATES, DEFAULT_MAX_DAILY_UPDATES); mMaxDynamicShortcuts = (int) parser.getLong( ConfigConstants.KEY_MAX_SHORTCUTS, DEFAULT_MAX_SHORTCUTS_PER_APP); final int iconDimensionDp = injectIsLowRamDevice() ? (int) parser.getLong( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM, DEFAULT_MAX_ICON_DIMENSION_LOWRAM_DP) : (int) parser.getLong( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP, DEFAULT_MAX_ICON_DIMENSION_DP); mMaxIconDimension = injectDipToPixel(iconDimensionDp); mIconPersistFormat = CompressFormat.valueOf( parser.getString(ConfigConstants.KEY_ICON_FORMAT, DEFAULT_ICON_PERSIST_FORMAT)); mIconPersistQuality = (int) parser.getLong( ConfigConstants.KEY_ICON_QUALITY, DEFAULT_ICON_PERSIST_QUALITY); return result; } @VisibleForTesting String injectShortcutManagerConstants() { return android.provider.Settings.Global.getString( mContext.getContentResolver(), android.provider.Settings.Global.SHORTCUT_MANAGER_CONSTANTS); } @VisibleForTesting int injectDipToPixel(int dip) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, mContext.getResources().getDisplayMetrics()); } Loading Loading @@ -1829,14 +1931,27 @@ public class ShortcutService extends IShortcutService.Stub { return handleDefaultCommands(cmd); } final PrintWriter pw = getOutPrintWriter(); int ret = 1; switch (cmd) { case "reset-package-throttling": return handleResetPackageThrottling(); ret = handleResetPackageThrottling(); break; case "reset-throttling": return handleResetThrottling(); ret = handleResetThrottling(); break; case "override-config": ret = handleOverrideConfig(); break; case "reset-config": ret = handleResetConfig(); break; default: return handleDefaultCommands(cmd); } if (ret == 0) { pw.println("Success"); } return ret; } @Override Loading @@ -1850,6 +1965,12 @@ public class ShortcutService extends IShortcutService.Stub { pw.println("cmd shortcut reset-throttling"); pw.println(" Reset throttling for all packages and users"); pw.println(); pw.println("cmd shortcut override-config CONFIG"); pw.println(" Override the configuration for testing (will last until reboot)"); pw.println(); pw.println("cmd shortcut reset-config"); pw.println(" Reset the configuration set with \"update-config\""); pw.println(); } private int handleResetThrottling() { Loading Loading @@ -1881,6 +2002,26 @@ public class ShortcutService extends IShortcutService.Stub { return 0; } private int handleOverrideConfig() { final PrintWriter pw = getOutPrintWriter(); final String config = getNextArgRequired(); synchronized (mLock) { if (!updateConfigurationLocked(config)) { pw.println("override-config failed. See logcat for details."); return 1; } } return 0; } private int handleResetConfig() { synchronized (mLock) { loadConfigurationLocked(); } return 0; } } // === Unit test support === Loading @@ -1903,6 +2044,7 @@ public class ShortcutService extends IShortcutService.Stub { return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER); } @VisibleForTesting boolean injectIsLowRamDevice() { return ActivityManager.isLowRamDeviceStatic(); } Loading @@ -1917,22 +2059,32 @@ public class ShortcutService extends IShortcutService.Stub { } @VisibleForTesting void setMaxDynamicShortcutsForTest(int max) { mMaxDynamicShortcuts = max; int getMaxDynamicShortcutsForTest() { return mMaxDynamicShortcuts; } @VisibleForTesting void setMaxDailyUpdatesForTest(int max) { mMaxDailyUpdates = max; int getMaxDailyUpdatesForTest() { return mMaxDailyUpdates; } @VisibleForTesting long getResetIntervalForTest() { return mResetInterval; } @VisibleForTesting int getMaxIconDimensionForTest() { return mMaxIconDimension; } @VisibleForTesting void setMaxIconDimensionForTest(int dimension) { mMaxIconDimension = dimension; CompressFormat getIconPersistFormatForTest() { return mIconPersistFormat; } @VisibleForTesting public void setResetIntervalForTest(long interval) { mResetInterval = interval; int getIconPersistQualityForTest() { return mIconPersistQuality; } }
services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java +63 −5 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.pm.ShortcutManager; import android.content.pm.ShortcutServiceInternal; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.BitmapFactory; import android.graphics.drawable.Icon; import android.os.Bundle; Loading @@ -42,6 +43,7 @@ import com.android.frameworks.servicestests.R; import com.android.internal.util.Preconditions; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.ShortcutService.ConfigConstants; import com.android.server.pm.ShortcutService.FileOutputStreamWithPath; import libcore.io.IoUtils; Loading Loading @@ -114,11 +116,20 @@ public class ShortcutManagerTest extends AndroidTestCase { } @Override void injectLoadConfigurationLocked() { setResetIntervalForTest(INTERVAL); setMaxDynamicShortcutsForTest(MAX_SHORTCUTS); setMaxDailyUpdatesForTest(MAX_DAILY_UPDATES); setMaxIconDimensionForTest(MAX_ICON_DIMENSION); String injectShortcutManagerConstants() { return ConfigConstants.KEY_RESET_INTERVAL_SEC + "=" + (INTERVAL / 1000) + "," + ConfigConstants.KEY_MAX_SHORTCUTS + "=" + MAX_SHORTCUTS + "," + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=" + MAX_DAILY_UPDATES + "," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=" + MAX_ICON_DIMENSION + "," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=" + MAX_ICON_DIMENSION_LOWRAM + "," + ConfigConstants.KEY_ICON_FORMAT + "=PNG," + ConfigConstants.KEY_ICON_QUALITY + "=100"; } @Override int injectDipToPixel(int dip) { return dip; } @Override Loading Loading @@ -151,6 +162,11 @@ public class ShortcutManagerTest extends AndroidTestCase { void injectValidateIconResPackage(ShortcutInfo shortcut, Icon icon) { // Can't check } @Override boolean injectIsLowRamDevice() { return mInjectdIsLowRamDevice; } } /** ShortcutManager with injection override methods. */ Loading Loading @@ -186,6 +202,8 @@ public class ShortcutManagerTest extends AndroidTestCase { private long mInjectedCurrentTimeLillis; private boolean mInjectdIsLowRamDevice; private int mInjectedCallingUid; private String mInjectedClientPackage; Loading Loading @@ -216,6 +234,8 @@ public class ShortcutManagerTest extends AndroidTestCase { private static final int MAX_ICON_DIMENSION = 128; private static final int MAX_ICON_DIMENSION_LOWRAM = 32; @Override protected void setUp() throws Exception { super.setUp(); Loading Loading @@ -676,6 +696,44 @@ public class ShortcutManagerTest extends AndroidTestCase { // TODO Add various broken cases. } public void testLoadConfig() { mService.updateConfigurationLocked( ConfigConstants.KEY_RESET_INTERVAL_SEC + "=123," + ConfigConstants.KEY_MAX_SHORTCUTS + "=4," + ConfigConstants.KEY_MAX_DAILY_UPDATES + "=5," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50," + ConfigConstants.KEY_ICON_FORMAT + "=WEBP," + ConfigConstants.KEY_ICON_QUALITY + "=75"); assertEquals(123000, mService.getResetIntervalForTest()); assertEquals(4, mService.getMaxDynamicShortcutsForTest()); assertEquals(5, mService.getMaxDailyUpdatesForTest()); assertEquals(100, mService.getMaxIconDimensionForTest()); assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest()); assertEquals(75, mService.getIconPersistQualityForTest()); mInjectdIsLowRamDevice = true; mService.updateConfigurationLocked( ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100," + ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50," + ConfigConstants.KEY_ICON_FORMAT + "=JPEG"); assertEquals(ShortcutService.DEFAULT_RESET_INTERVAL_SEC * 1000, mService.getResetIntervalForTest()); assertEquals(ShortcutService.DEFAULT_MAX_SHORTCUTS_PER_APP, mService.getMaxDynamicShortcutsForTest()); assertEquals(ShortcutService.DEFAULT_MAX_DAILY_UPDATES, mService.getMaxDailyUpdatesForTest()); assertEquals(50, mService.getMaxIconDimensionForTest()); assertEquals(CompressFormat.JPEG, mService.getIconPersistFormatForTest()); assertEquals(ShortcutService.DEFAULT_ICON_PERSIST_QUALITY, mService.getIconPersistQualityForTest()); } // === Test for app side APIs === /** Test for {@link android.content.pm.ShortcutManager#getMaxDynamicShortcutCount()} */ Loading