diff options
| author | 2023-12-05 17:02:52 +0000 | |
|---|---|---|
| committer | 2023-12-05 17:02:52 +0000 | |
| commit | 2faf8430032cac0ac0d09989fe445b86b92a2a3c (patch) | |
| tree | eaef6d899ad7c9e7ff844edf1a94b51173a49ecd | |
| parent | 6e42edd25e507411a74ff0bf9457089ed8b7053b (diff) | |
| parent | 25cc875af2119c9ea32bd78fa17e24ba31faec30 (diff) | |
Merge "Store rule icon res name" into main
6 files changed, 116 insertions, 35 deletions
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index c486b6a6a46e..f6128ea80c3b 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -683,7 +683,7 @@ public class ZenModeConfig implements Parcelable { if (Flags.modesApi()) { rt.zenDeviceEffects = readZenDeviceEffectsXml(parser); rt.allowManualInvocation = safeBoolean(parser, RULE_ATT_ALLOW_MANUAL, false); - rt.iconResId = safeInt(parser, RULE_ATT_ICON, 0); + rt.iconResName = parser.getAttributeValue(null, RULE_ATT_ICON); rt.triggerDescription = parser.getAttributeValue(null, RULE_ATT_TRIGGER_DESC); rt.type = safeInt(parser, RULE_ATT_TYPE, AutomaticZenRule.TYPE_UNKNOWN); } @@ -725,7 +725,9 @@ public class ZenModeConfig implements Parcelable { out.attributeBoolean(null, RULE_ATT_MODIFIED, rule.modified); if (Flags.modesApi()) { out.attributeBoolean(null, RULE_ATT_ALLOW_MANUAL, rule.allowManualInvocation); - out.attributeInt(null, RULE_ATT_ICON, rule.iconResId); + if (rule.iconResName != null) { + out.attribute(null, RULE_ATT_ICON, rule.iconResName); + } if (rule.triggerDescription != null) { out.attribute(null, RULE_ATT_TRIGGER_DESC, rule.triggerDescription); } @@ -1918,8 +1920,7 @@ public class ZenModeConfig implements Parcelable { public String pkg; public int type = AutomaticZenRule.TYPE_UNKNOWN; public String triggerDescription; - // TODO (b/308672670): switch to string res name - public int iconResId; + public String iconResName; public boolean allowManualInvocation; public ZenRule() { } @@ -1950,7 +1951,7 @@ public class ZenModeConfig implements Parcelable { pkg = source.readString(); if (Flags.modesApi()) { allowManualInvocation = source.readBoolean(); - iconResId = source.readInt(); + iconResName = source.readString(); triggerDescription = source.readString(); type = source.readInt(); } @@ -1997,7 +1998,7 @@ public class ZenModeConfig implements Parcelable { dest.writeString(pkg); if (Flags.modesApi()) { dest.writeBoolean(allowManualInvocation); - dest.writeInt(iconResId); + dest.writeString(iconResName); dest.writeString(triggerDescription); dest.writeInt(type); } @@ -2026,7 +2027,7 @@ public class ZenModeConfig implements Parcelable { if (Flags.modesApi()) { sb.append(",deviceEffects=").append(zenDeviceEffects) .append(",allowManualInvocation=").append(allowManualInvocation) - .append(",iconResId=").append(iconResId) + .append(",iconResName=").append(iconResName) .append(",triggerDescription=").append(triggerDescription) .append(",type=").append(type); } @@ -2085,7 +2086,7 @@ public class ZenModeConfig implements Parcelable { return finalEquals && Objects.equals(other.zenDeviceEffects, zenDeviceEffects) && other.allowManualInvocation == allowManualInvocation - && other.iconResId == iconResId + && Objects.equals(other.iconResName, iconResName) && Objects.equals(other.triggerDescription, triggerDescription) && other.type == type; } @@ -2098,7 +2099,7 @@ public class ZenModeConfig implements Parcelable { if (Flags.modesApi()) { return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, component, configurationActivity, pkg, id, enabler, zenPolicy, - zenDeviceEffects, modified, allowManualInvocation, iconResId, + zenDeviceEffects, modified, allowManualInvocation, iconResName, triggerDescription, type); } return Objects.hash(enabled, snoozing, name, zenMode, conditionId, condition, diff --git a/core/java/android/service/notification/ZenModeDiff.java b/core/java/android/service/notification/ZenModeDiff.java index 9538df1db43a..d87e75884802 100644 --- a/core/java/android/service/notification/ZenModeDiff.java +++ b/core/java/android/service/notification/ZenModeDiff.java @@ -464,7 +464,7 @@ public class ZenModeDiff { public static final String FIELD_MODIFIED = "modified"; public static final String FIELD_PKG = "pkg"; public static final String FIELD_ALLOW_MANUAL = "allowManualInvocation"; - public static final String FIELD_ICON_RES = "iconResId"; + public static final String FIELD_ICON_RES = "iconResName"; public static final String FIELD_TRIGGER_DESCRIPTION = "triggerDescription"; public static final String FIELD_TYPE = "type"; // NOTE: new field strings must match the variable names in ZenModeConfig.ZenRule @@ -559,8 +559,8 @@ public class ZenModeDiff { addField(FIELD_ALLOW_MANUAL, new FieldDiff<>(from.allowManualInvocation, to.allowManualInvocation)); } - if (!Objects.equals(from.iconResId, to.iconResId)) { - addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResId, to.iconResId)); + if (!Objects.equals(from.iconResName, to.iconResName)) { + addField(FIELD_ICON_RES, new FieldDiff<>(from.iconResName, to.iconResName)); } } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index d0ded63162db..5c37eeaba180 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -28,6 +28,8 @@ import static android.service.notification.NotificationServiceProto.ROOT_CONFIG; import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE; import android.annotation.IntDef; +import android.annotation.DrawableRes; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SuppressLint; import android.annotation.UserIdInt; @@ -79,6 +81,7 @@ import android.service.notification.ZenModeConfig; import android.service.notification.ZenModeConfig.ZenRule; import android.service.notification.ZenModeProto; import android.service.notification.ZenPolicy; +import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.Log; @@ -868,12 +871,13 @@ public class ZenModeHelper { return null; } - private static void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule, + @VisibleForTesting + void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew, @ChangeOrigin int origin) { - // TODO: b/308671593,b/311406021 - Handle origins more precisely: - // - FROM_USER can override anything and updates bitmask of user-modified fields; - // - FROM_SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask; - // - FROM_APP can only update if not user-modified. + // TODO: b/308671593,b/311406021 - Handle origins more precisely: + // - FROM_USER can override anything and updates bitmask of user-modified fields; + // - FROM_SYSTEM_OR_SYSTEMUI can override anything and preserves bitmask; + // - FROM_APP can only update if not user-modified. if (rule.enabled != automaticZenRule.isEnabled()) { rule.snoozing = false; } @@ -902,14 +906,14 @@ public class ZenModeHelper { if (Flags.modesApi()) { rule.allowManualInvocation = automaticZenRule.isManualInvocationAllowed(); - rule.iconResId = automaticZenRule.getIconResId(); + rule.iconResName = drawableResIdToResName(rule.pkg, automaticZenRule.getIconResId()); rule.triggerDescription = automaticZenRule.getTriggerDescription(); rule.type = automaticZenRule.getType(); } } - /** " - * Fix" {@link ZenDeviceEffects} that are being stored as part of a new or updated ZenRule. + /** + * Fix {@link ZenDeviceEffects} that are being stored as part of a new or updated ZenRule. * * <ul> * <li> Apps cannot turn on hidden effects (those tagged as {@code @hide}) since they are @@ -952,13 +956,13 @@ public class ZenModeHelper { } } - private static AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) { + private AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) { AutomaticZenRule azr; if (Flags.modesApi()) { azr = new AutomaticZenRule.Builder(rule.name, rule.conditionId) .setManualInvocationAllowed(rule.allowManualInvocation) .setCreationTime(rule.creationTime) - .setIconResId(rule.iconResId) + .setIconResId(drawableResNameToResId(rule.pkg, rule.iconResName)) .setType(rule.type) .setZenPolicy(rule.zenPolicy) .setDeviceEffects(rule.zenDeviceEffects) @@ -1942,6 +1946,35 @@ public class ZenModeHelper { .build(); } + private int drawableResNameToResId(String packageName, String resourceName) { + if (TextUtils.isEmpty(resourceName)) { + return 0; + } + try { + final Resources res = mPm.getResourcesForApplication(packageName); + return res.getIdentifier(resourceName, null, null); + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "cannot load rule icon for pkg", e); + } + return 0; + } + + private String drawableResIdToResName(String packageName, @DrawableRes int resId) { + if (resId == 0) { + return null; + } + try { + final Resources res = mPm.getResourcesForApplication(packageName); + final String fullName = res.getResourceName(resId); + + return fullName; + } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { + Log.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName + + ". Resource IDs may change when the application is upgraded, and the system" + + " may not be able to find the correct resource."); + return null; + } + } private final class Metrics extends Callback { private static final String COUNTER_MODE_PREFIX = "dnd_mode_"; private static final String COUNTER_TYPE_PREFIX = "dnd_type_"; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index cad8bacab8e0..3185c50c27ef 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -75,7 +75,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { private final String TRIGGER_DESC = "Every Night, 10pm to 6am"; private final int TYPE = TYPE_BEDTIME; private final boolean ALLOW_MANUAL = true; - private final int ICON_RES_ID = 1234; + private final String ICON_RES_NAME = "icon_res"; private final int INTERRUPTION_FILTER = Settings.Global.ZEN_MODE_ALARMS; private final boolean ENABLED = true; private final int CREATION_TIME = 123; @@ -347,7 +347,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.allowManualInvocation = ALLOW_MANUAL; rule.type = TYPE; - rule.iconResId = ICON_RES_ID; + rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; Parcel parcel = Parcel.obtain(); @@ -369,7 +369,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.zenMode, parceled.zenMode); assertEquals(rule.allowManualInvocation, parceled.allowManualInvocation); - assertEquals(rule.iconResId, parceled.iconResId); + assertEquals(rule.iconResName, parceled.iconResName); assertEquals(rule.type, parceled.type); assertEquals(rule.triggerDescription, parceled.triggerDescription); assertEquals(rule.zenPolicy, parceled.zenPolicy); @@ -448,7 +448,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { rule.allowManualInvocation = ALLOW_MANUAL; rule.type = TYPE; - rule.iconResId = ICON_RES_ID; + rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -477,7 +477,7 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.allowManualInvocation, fromXml.allowManualInvocation); assertEquals(rule.type, fromXml.type); assertEquals(rule.triggerDescription, fromXml.triggerDescription); - assertEquals(rule.iconResId, fromXml.iconResId); + assertEquals(rule.iconResName, fromXml.iconResName); } @Test diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java index 4e684d0eb036..93cd44eb7966 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeDiffTest.java @@ -299,7 +299,7 @@ public class ZenModeDiffTest extends UiServiceTestCase { if (android.app.Flags.modesApi()) { rule.allowManualInvocation = true; rule.type = AutomaticZenRule.TYPE_SCHEDULE_TIME; - rule.iconResId = 123; + rule.iconResName = "res"; rule.triggerDescription = "At night"; rule.zenDeviceEffects = new ZenDeviceEffects.Builder() .setShouldDimWallpaper(true) 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 4d25eaab1f49..b1fdec911d86 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -81,6 +81,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; import android.annotation.Nullable; import android.annotation.SuppressLint; @@ -192,8 +193,12 @@ public class ZenModeHelperTest extends UiServiceTestCase { private static final String TRIGGER_DESC = "Every Night, 10pm to 6am"; private static final int TYPE = TYPE_BEDTIME; private static final boolean ALLOW_MANUAL = true; - private static final int ICON_RES_ID = 1234; - private static final int INTERRUPTION_FILTER = Settings.Global.ZEN_MODE_ALARMS; + private static final String ICON_RES_NAME = "com.android.server.notification:drawable/res_name"; + private static final int ICON_RES_ID = 123; + private static final int INTERRUPTION_FILTER_ZR = Settings.Global.ZEN_MODE_ALARMS; + + private static final int INTERRUPTION_FILTER_AZR + = NotificationManager.INTERRUPTION_FILTER_ALARMS; private static final boolean ENABLED = true; private static final int CREATION_TIME = 123; @@ -216,8 +221,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { MockitoAnnotations.initMocks(this); mTestableLooper = TestableLooper.get(this); + mContext.ensureTestableResources(); mContentResolver = mContext.getContentResolver(); - mResources = spy(mContext.getResources()); + mResources = mock(Resources.class, withSettings() + .spiedInstance(mContext.getResources())); String pkg = mContext.getPackageName(); try { when(mResources.getXml(R.xml.default_zen_mode_config)).thenReturn( @@ -226,6 +233,10 @@ public class ZenModeHelperTest extends UiServiceTestCase { Log.d("ZenModeHelperTest", "Couldn't mock default zen mode config xml file err=" + e.toString()); } + when(mResources.getIdentifier(ICON_RES_NAME, null, null)).thenReturn(ICON_RES_ID); + when(mResources.getResourceName(ICON_RES_ID)).thenReturn(ICON_RES_NAME); + when(mPackageManager.getResourcesForApplication(anyString())).thenReturn( + mResources); when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOps); when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager); @@ -3053,7 +3064,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { rule.enabled = ENABLED; rule.creationTime = 123; rule.id = "id"; - rule.zenMode = INTERRUPTION_FILTER; + rule.zenMode = INTERRUPTION_FILTER_ZR; rule.modified = true; rule.name = NAME; rule.snoozing = true; @@ -3062,7 +3073,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { rule.allowManualInvocation = ALLOW_MANUAL; rule.type = TYPE; - rule.iconResId = ICON_RES_ID; + rule.iconResName = ICON_RES_NAME; rule.triggerDescription = TRIGGER_DESC; mZenModeHelper.mConfig.automaticRules.put(rule.id, rule); @@ -3071,8 +3082,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertEquals(NAME, actual.getName()); assertEquals(OWNER, actual.getOwner()); assertEquals(CONDITION_ID, actual.getConditionId()); - assertEquals(NotificationManager.INTERRUPTION_FILTER_ALARMS, - actual.getInterruptionFilter()); + assertEquals(INTERRUPTION_FILTER_AZR, actual.getInterruptionFilter()); assertEquals(ENABLED, actual.isEnabled()); assertEquals(POLICY, actual.getZenPolicy()); assertEquals(CONFIG_ACTIVITY, actual.getConfigurationActivity()); @@ -3085,6 +3095,43 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + public void automaticZenRuleToZenRule_allFields() { + mSetFlagsRule.enableFlags(Flags.FLAG_MODES_API); + when(mPackageManager.getPackagesForUid(anyInt())).thenReturn( + new String[] {OWNER.getPackageName()}); + + AutomaticZenRule azr = new AutomaticZenRule.Builder(NAME, CONDITION_ID) + .setEnabled(true) + .setConfigurationActivity(CONFIG_ACTIVITY) + .setTriggerDescription(TRIGGER_DESC) + .setCreationTime(CREATION_TIME) + .setIconResId(ICON_RES_ID) + .setZenPolicy(POLICY) + .setInterruptionFilter(INTERRUPTION_FILTER_AZR) + .setType(TYPE) + .setOwner(OWNER) + .setManualInvocationAllowed(ALLOW_MANUAL) + .build(); + + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + + mZenModeHelper.populateZenRule(OWNER.getPackageName(), azr, rule, true, FROM_APP); + + assertEquals(NAME, rule.name); + assertEquals(OWNER, rule.component); + assertEquals(CONDITION_ID, rule.conditionId); + assertEquals(INTERRUPTION_FILTER_ZR, rule.zenMode); + assertEquals(ENABLED, rule.enabled); + assertEquals(POLICY, rule.zenPolicy); + assertEquals(CONFIG_ACTIVITY, rule.configurationActivity); + assertEquals(TYPE, rule.type); + assertEquals(ALLOW_MANUAL, rule.allowManualInvocation); + assertEquals(OWNER.getPackageName(), rule.getPkg()); + assertEquals(ICON_RES_NAME, rule.iconResName); + assertEquals(TRIGGER_DESC, rule.triggerDescription); + } + + @Test public void testUpdateAutomaticRule_disabled_triggersBroadcast() throws Exception { setupZenConfig(); |