diff options
| author | 2024-08-23 13:59:46 +0200 | |
|---|---|---|
| committer | 2024-08-25 16:15:55 +0200 | |
| commit | 7a095ee6ad5591c523d22758ec8c5f9b43c1629a (patch) | |
| tree | 0f2fb6c1e684e71844279e0097e63533e4544e3a | |
| parent | 28b2ac4c478726bd2800027e2f4b7f6e7f547304 (diff) | |
Don't set the app launcher icon as the icon for implicit rules
And clear it from existing rules.
Many app icons don't have a monochrome variant, and even when they do they might not be appropriate for some surfaces where mode icons are displayed. Instead, use a default icon (which the user can customize, if they want).
Should be ok to change since it wasn't visible anywhere before MODES_UI.
Flag: android.app.modes_ui
Fixes: 361597532
Test: atest ZenModeHelperTest
Change-Id: I47d8b132287ffc50a74316898c2071fbb31e13ed
7 files changed, 105 insertions, 68 deletions
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 57acc71c20ea..918e591069fb 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -241,10 +241,11 @@ public class ZenModeConfig implements Parcelable { // ZenModeConfig XML versions distinguishing key changes. public static final int XML_VERSION_ZEN_UPGRADE = 8; public static final int XML_VERSION_MODES_API = 11; + public static final int XML_VERSION_MODES_UI = 12; - // TODO: b/310620812 - Update XML_VERSION and update default_zen_config.xml accordingly when - // modes_api is inlined. - private static final int XML_VERSION = 10; + // TODO: b/310620812, b/344831624 - Update XML_VERSION and update default_zen_config.xml + // accordingly when modes_api / modes_ui are inlined. + private static final int XML_VERSION_PRE_MODES = 10; public static final String ZEN_TAG = "zen"; private static final String ZEN_ATT_VERSION = "version"; private static final String ZEN_ATT_USER = "user"; @@ -952,7 +953,13 @@ public class ZenModeConfig implements Parcelable { } public static int getCurrentXmlVersion() { - return Flags.modesApi() ? XML_VERSION_MODES_API : XML_VERSION; + if (Flags.modesUi()) { + return XML_VERSION_MODES_UI; + } else if (Flags.modesApi()) { + return XML_VERSION_MODES_API; + } else { + return XML_VERSION_PRE_MODES; + } } public static ZenModeConfig readXml(TypedXmlPullParser parser) @@ -2607,7 +2614,7 @@ public class ZenModeConfig implements Parcelable { @AutomaticZenRule.Type public int type = AutomaticZenRule.TYPE_UNKNOWN; public String triggerDescription; - public String iconResName; + @Nullable public String iconResName; public boolean allowManualInvocation; @AutomaticZenRule.ModifiableField public int userModifiedFields; @ZenPolicy.ModifiableField public int zenPolicyUserModifiedFields; diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java index d36b55f8961a..9fa8fc3cc647 100644 --- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java +++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java @@ -286,8 +286,7 @@ public class ZenMode implements Parcelable { /** * Returns the mode icon -- which can be either app-provided (via {@code addAutomaticZenRule}), - * user-chosen (via the icon picker in Settings), the app's launcher icon for implicit rules - * (in its monochrome variant, if available), or a default icon based on the mode type. + * user-chosen (via the icon picker in Settings), or a default icon based on the mode type. */ @NonNull public ListenableFuture<Drawable> getIcon(@NonNull Context context, @@ -300,23 +299,6 @@ public class ZenMode implements Parcelable { return iconLoader.getIcon(context, mRule); } - /** - * Returns an alternative mode icon. The difference with {@link #getIcon} is that it's the - * basic DND icon not only for Manual DND, but also for <em>implicit rules</em>. As such, it's - * suitable for places where showing the launcher icon of an app could be confusing, such as - * the status bar or lockscreen. - */ - @NonNull - public ListenableFuture<Drawable> getLockscreenIcon(@NonNull Context context, - @NonNull ZenIconLoader iconLoader) { - if (mKind == Kind.MANUAL_DND || mKind == Kind.IMPLICIT) { - return Futures.immediateFuture(requireNonNull( - context.getDrawable(R.drawable.ic_do_not_disturb_on_24dp))); - } - - return iconLoader.getIcon(context, mRule); - } - @NonNull public ZenPolicy getPolicy() { switch (mRule.getInterruptionFilter()) { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java index f533e77bb33e..32216fadfb0d 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java @@ -322,41 +322,6 @@ public class ZenModeTest { verify(iconLoader).getIcon(any(), eq(IMPLICIT_ZEN_RULE)); } - @Test - public void getLockscreenIcon_normalMode_loadsIconNormally() { - ZenIconLoader iconLoader = mock(ZenIconLoader.class); - ZenMode mode = new ZenMode("id", ZEN_RULE, zenConfigRuleFor(ZEN_RULE, false)); - - ListenableFuture<Drawable> unused = mode.getLockscreenIcon( - RuntimeEnvironment.getApplication(), iconLoader); - - verify(iconLoader).getIcon(any(), eq(ZEN_RULE)); - } - - @Test - public void getLockscreenIcon_manualDnd_returnsFixedIcon() { - ZenIconLoader iconLoader = mock(ZenIconLoader.class); - - ListenableFuture<Drawable> future = TestModeBuilder.MANUAL_DND_INACTIVE.getLockscreenIcon( - RuntimeEnvironment.getApplication(), iconLoader); - - assertThat(future.isDone()).isTrue(); - verify(iconLoader, never()).getIcon(any(), any()); - } - - @Test - public void getLockscreenIcon_implicitMode_returnsFixedIcon() { - ZenIconLoader iconLoader = mock(ZenIconLoader.class); - ZenMode mode = new ZenMode(IMPLICIT_RULE_ID, IMPLICIT_ZEN_RULE, - zenConfigRuleFor(IMPLICIT_ZEN_RULE, false)); - - ListenableFuture<Drawable> future = mode.getLockscreenIcon( - RuntimeEnvironment.getApplication(), iconLoader); - - assertThat(future.isDone()).isTrue(); - verify(iconLoader, never()).getIcon(any(), any()); - } - private static void assertUnparceledIsEqualToOriginal(String type, ZenMode original) { Parcel parcel = Parcel.obtain(); try { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt index 5f5b26514de8..3f18fc2066eb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/modes/domain/interactor/ModesTileDataInteractor.kt @@ -57,7 +57,7 @@ constructor( isActivated = modes.isNotEmpty(), icon = if (Flags.modesApi() && Flags.modesUi() && Flags.modesUiIcons()) - zenModeInteractor.getActiveModeIcon(context, modes) + zenModeInteractor.getActiveModeIcon(modes) else null, activeModes = modes.map { it.name } ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt index f16fcb5d4e82..d351da68e1c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/domain/interactor/ZenModeInteractor.kt @@ -95,10 +95,6 @@ constructor( return mode.getIcon(context, iconLoader).await().asIcon() } - suspend fun getLockscreenModeIcon(mode: ZenMode): Icon { - return mode.getLockscreenIcon(context, iconLoader).await().asIcon() - } - /** * Given the list of modes (which may include zero or more currently active modes), returns an * icon representing the active mode, if any (or, if multiple modes are active, to the most @@ -106,8 +102,8 @@ constructor( * standard DND icon for implicit modes, instead of the launcher icon of the associated * package). */ - suspend fun getActiveModeIcon(context: Context, modes: List<ZenMode>): Icon? { - return getMainActiveMode(modes)?.let { m -> getLockscreenModeIcon(m) } + suspend fun getActiveModeIcon(modes: List<ZenMode>): Icon? { + return getMainActiveMode(modes)?.let { m -> getModeIcon(m) } } fun activateMode(zenMode: ZenMode) { diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index ee3f48d9bd3f..f12dfa2ff691 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -757,7 +757,9 @@ public class ZenModeHelper { try { ApplicationInfo applicationInfo = mPm.getApplicationInfo(pkg, 0); rule.name = applicationInfo.loadLabel(mPm).toString(); - rule.iconResName = drawableResIdToResName(pkg, applicationInfo.icon); + if (!Flags.modesUi()) { + rule.iconResName = drawableResIdToResName(pkg, applicationInfo.icon); + } } catch (PackageManager.NameNotFoundException e) { // Should not happen, since it's the app calling us (?) Log.w(TAG, "Package not found for creating implicit zen rule"); @@ -1742,6 +1744,15 @@ public class ZenModeHelper { manualRulePolicy.overwrittenWith(automaticRule.zenPolicy); } } + + if (Flags.modesApi() && Flags.modesUi() + && config.version < ZenModeConfig.XML_VERSION_MODES_UI) { + // Clear icons from implicit rules. App icons are not suitable for some + // surfaces, so juse use a default (the user can select a different one). + if (ZenModeConfig.isImplicitRuleId(automaticRule.id)) { + automaticRule.iconResName = null; + } + } } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index dd2b84504e51..49036d5945d2 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -2186,6 +2186,80 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void testReadXml_upgradeToModesUi_resetsImplicitRuleIcon() throws Exception { + setupZenConfig(); + mZenModeHelper.mConfig.automaticRules.clear(); + + ZenRule implicitRuleWithModesUi = expectedImplicitRule("pkg", + ZEN_MODE_IMPORTANT_INTERRUPTIONS, POLICY, null); + + // Add one implicit rule in the pre-MODES_UI configuration. + ZenRule implicitRuleBeforeModesUi = implicitRuleWithModesUi.copy(); + implicitRuleBeforeModesUi.iconResName = "pkg_icon"; + mZenModeHelper.mConfig.automaticRules.put(implicitRuleBeforeModesUi.id, + implicitRuleBeforeModesUi); + // Plus one other normal rule. + ZenRule anotherRule = newZenRule("other_pkg", Instant.now(), null); + anotherRule.id = "other_rule"; + anotherRule.iconResName = "other_icon"; + anotherRule.type = TYPE_IMMERSIVE; + mZenModeHelper.mConfig.automaticRules.put(anotherRule.id, anotherRule); + + // Write with pre-modes-ui = (modes_api) version, then re-read. + ByteArrayOutputStream baos = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_API); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // Implicit rule was updated. + assertThat(mZenModeHelper.mConfig.automaticRules.get(implicitRuleBeforeModesUi.id)) + .isEqualTo(implicitRuleWithModesUi); + + // The other rule was untouched. + assertThat(mZenModeHelper.mConfig.automaticRules.get(anotherRule.id)) + .isEqualTo(anotherRule); + } + + @Test + @EnableFlags({FLAG_MODES_API, FLAG_MODES_UI}) + public void testReadXml_onModesUi_implicitRulesUntouched() throws Exception { + setupZenConfig(); + mZenModeHelper.mConfig.automaticRules.clear(); + + // Add one implicit rule already in its post-modes-UI configuration, also customized with + // an icon; + ZenRule implicitRuleWithModesUi = expectedImplicitRule("pkg", + ZEN_MODE_IMPORTANT_INTERRUPTIONS, POLICY, null); + implicitRuleWithModesUi.iconResName = "icon_chosen_by_user"; + mZenModeHelper.mConfig.automaticRules.put(implicitRuleWithModesUi.id, + implicitRuleWithModesUi); + + // Plus one other normal rule. + ZenRule anotherRule = newZenRule("other_pkg", Instant.now(), null); + anotherRule.id = "other_rule"; + anotherRule.iconResName = "other_icon"; + anotherRule.type = TYPE_IMMERSIVE; + mZenModeHelper.mConfig.automaticRules.put(anotherRule.id, anotherRule); + + // Write with modes_ui version, then re-read. + ByteArrayOutputStream baos = writeXmlAndPurge(ZenModeConfig.XML_VERSION_MODES_UI); + TypedXmlPullParser parser = Xml.newFastPullParser(); + parser.setInput(new BufferedInputStream( + new ByteArrayInputStream(baos.toByteArray())), null); + parser.nextTag(); + mZenModeHelper.readXml(parser, false, UserHandle.USER_ALL); + + // Both rules were untouched + assertThat(mZenModeHelper.mConfig.automaticRules.get(implicitRuleWithModesUi.id)) + .isEqualTo(implicitRuleWithModesUi); + assertThat(mZenModeHelper.mConfig.automaticRules.get(anotherRule.id)) + .isEqualTo(anotherRule); + } + + @Test public void testCountdownConditionSubscription() throws Exception { ZenModeConfig config = new ZenModeConfig(); mZenModeHelper.mConfig = config; @@ -6809,7 +6883,9 @@ public class ZenModeHelperTest extends UiServiceTestCase { rule.zenPolicy = policy; rule.pkg = ownerPkg; rule.name = CUSTOM_APP_LABEL; - rule.iconResName = ICON_RES_NAME; + if (!Flags.modesUi()) { + rule.iconResName = ICON_RES_NAME; + } rule.triggerDescription = mContext.getString(R.string.zen_mode_implicit_trigger_description, CUSTOM_APP_LABEL); rule.type = AutomaticZenRule.TYPE_OTHER; |