Clean up orphaned zen rules, synchronize better.
(If a rule was restored to the device but the user didn't restore
the matching app).
Bug: 25472361
Change-Id: Icaefd0d1fca78ff351937fbe553ae72922a5457f
diff --git a/services/core/java/com/android/server/notification/ZenModeConditions.java b/services/core/java/com/android/server/notification/ZenModeConditions.java
index cee9ec8..9cdece5 100644
--- a/services/core/java/com/android/server/notification/ZenModeConditions.java
+++ b/services/core/java/com/android/server/notification/ZenModeConditions.java
@@ -109,7 +109,6 @@
if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition);
ZenModeConfig config = mHelper.getConfig();
if (config == null) return;
- config = config.copy();
boolean updated = updateCondition(id, condition, config.manualRule);
for (ZenRule automaticRule : config.automaticRules.values()) {
updated |= updateCondition(id, condition, automaticRule);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 6030bab..85c3cf8 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -77,6 +77,9 @@
static final String TAG = "ZenModeHelper";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ // The amount of time rules instances can exist without their owning app being installed.
+ private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
+
private final Context mContext;
private final H mHandler;
private final SettingsObserver mSettingsObserver;
@@ -93,6 +96,7 @@
private int mUser = UserHandle.USER_SYSTEM;
private ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
+ private PackageManager mPm;
private boolean mEffectsSuppressed;
public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
@@ -170,7 +174,9 @@
if (mAudioManager != null) {
mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
}
+ mPm = mContext.getPackageManager();
mHandler.postMetricsTimer();
+ cleanUpZenRules();
evaluateZenMode("onSystemReady", true);
}
@@ -184,7 +190,10 @@
config = mDefaultConfig.copy();
config.user = user;
}
- setConfig(config, "onUserSwitched");
+ synchronized (mConfig) {
+ setConfig(config, "onUserSwitched");
+ }
+ cleanUpZenRules();
}
public void onUserRemoved(int user) {
@@ -253,14 +262,15 @@
throw new IllegalArgumentException("Rule already exists");
}
newConfig = mConfig.copy();
- }
- ZenRule rule = new ZenRule();
- populateZenRule(automaticZenRule, rule, true);
- newConfig.automaticRules.put(rule.id, rule);
- if (setConfig(newConfig, reason, true)) {
- return createAutomaticZenRule(rule);
- } else {
- return null;
+
+ ZenRule rule = new ZenRule();
+ populateZenRule(automaticZenRule, rule, true);
+ newConfig.automaticRules.put(rule.id, rule);
+ if (setConfig(newConfig, reason, true)) {
+ return createAutomaticZenRule(rule);
+ } else {
+ return null;
+ }
}
}
@@ -273,21 +283,21 @@
+ " reason=" + reason);
}
newConfig = mConfig.copy();
- }
- final String ruleId = automaticZenRule.getId();
- ZenModeConfig.ZenRule rule;
- if (ruleId == null) {
- throw new IllegalArgumentException("Rule doesn't exist");
- } else {
- rule = newConfig.automaticRules.get(ruleId);
- if (rule == null || !canManageAutomaticZenRule(rule)) {
- throw new SecurityException(
- "Cannot update rules not owned by your condition provider");
+ final String ruleId = automaticZenRule.getId();
+ ZenModeConfig.ZenRule rule;
+ if (ruleId == null) {
+ throw new IllegalArgumentException("Rule doesn't exist");
+ } else {
+ rule = newConfig.automaticRules.get(ruleId);
+ if (rule == null || !canManageAutomaticZenRule(rule)) {
+ throw new SecurityException(
+ "Cannot update rules not owned by your condition provider");
+ }
}
+ populateZenRule(automaticZenRule, rule, false);
+ newConfig.automaticRules.put(ruleId, rule);
+ return setConfig(newConfig, reason, true);
}
- populateZenRule(automaticZenRule, rule, false);
- newConfig.automaticRules.put(ruleId, rule);
- return setConfig(newConfig, reason, true);
}
public boolean removeAutomaticZenRule(String id, String reason) {
@@ -295,17 +305,17 @@
synchronized (mConfig) {
if (mConfig == null) return false;
newConfig = mConfig.copy();
+ ZenRule rule = newConfig.automaticRules.get(id);
+ if (rule == null) return false;
+ if (canManageAutomaticZenRule(rule)) {
+ newConfig.automaticRules.remove(id);
+ if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
+ } else {
+ throw new SecurityException(
+ "Cannot delete rules not owned by your condition provider");
+ }
+ return setConfig(newConfig, reason, true);
}
- ZenRule rule = newConfig.automaticRules.get(id);
- if (rule == null) return false;
- if (canManageAutomaticZenRule(rule)) {
- newConfig.automaticRules.remove(id);
- if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
- } else {
- throw new SecurityException(
- "Cannot delete rules not owned by your condition provider");
- }
- return setConfig(newConfig, reason, true);
}
public boolean removeAutomaticZenRules(String packageName, String reason) {
@@ -313,15 +323,15 @@
synchronized (mConfig) {
if (mConfig == null) return false;
newConfig = mConfig.copy();
- }
- for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
- ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
- if (rule.component.getPackageName().equals(packageName)
- && canManageAutomaticZenRule(rule)) {
- newConfig.automaticRules.removeAt(i);
+ for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
+ ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
+ if (rule.component.getPackageName().equals(packageName)
+ && canManageAutomaticZenRule(rule)) {
+ newConfig.automaticRules.removeAt(i);
+ }
}
+ return setConfig(newConfig, reason, true);
}
- return setConfig(newConfig, reason, true);
}
public boolean canManageAutomaticZenRule(ZenRule rule) {
@@ -332,8 +342,7 @@
== PackageManager.PERMISSION_GRANTED) {
return true;
} else {
- String[] packages =
- mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
if (packages != null) {
final int packageCount = packages.length;
for (int i = 0; i < packageCount; i++) {
@@ -384,22 +393,22 @@
+ " conditionId=" + conditionId + " reason=" + reason
+ " setRingerMode=" + setRingerMode);
newConfig = mConfig.copy();
- }
- if (zenMode == Global.ZEN_MODE_OFF) {
- newConfig.manualRule = null;
- for (ZenRule automaticRule : newConfig.automaticRules.values()) {
- if (automaticRule.isAutomaticActive()) {
- automaticRule.snoozing = true;
+ if (zenMode == Global.ZEN_MODE_OFF) {
+ newConfig.manualRule = null;
+ for (ZenRule automaticRule : newConfig.automaticRules.values()) {
+ if (automaticRule.isAutomaticActive()) {
+ automaticRule.snoozing = true;
+ }
}
+ } else {
+ final ZenRule newRule = new ZenRule();
+ newRule.enabled = true;
+ newRule.zenMode = zenMode;
+ newRule.conditionId = conditionId;
+ newConfig.manualRule = newRule;
}
- } else {
- final ZenRule newRule = new ZenRule();
- newRule.enabled = true;
- newRule.zenMode = zenMode;
- newRule.conditionId = conditionId;
- newConfig.manualRule = newRule;
+ setConfig(newConfig, reason, setRingerMode);
}
- setConfig(newConfig, reason, setRingerMode);
}
public void dump(PrintWriter pw, String prefix) {
@@ -450,16 +459,20 @@
return;
}
config.manualRule = null; // don't restore the manual rule
+ long time = System.currentTimeMillis();
if (config.automaticRules != null) {
for (ZenRule automaticRule : config.automaticRules.values()) {
// don't restore transient state from restored automatic rules
automaticRule.snoozing = false;
automaticRule.condition = null;
+ automaticRule.creationTime = time;
}
}
}
if (DEBUG) Log.d(TAG, "readXml");
- setConfig(config, "readXml");
+ synchronized (mConfig) {
+ setConfig(config, "readXml");
+ }
}
}
@@ -484,11 +497,39 @@
public void setNotificationPolicy(Policy policy) {
if (policy == null || mConfig == null) return;
- final ZenModeConfig newConfig = mConfig.copy();
- newConfig.applyNotificationPolicy(policy);
- setConfig(newConfig, "setNotificationPolicy");
+ synchronized (mConfig) {
+ final ZenModeConfig newConfig = mConfig.copy();
+ newConfig.applyNotificationPolicy(policy);
+ setConfig(newConfig, "setNotificationPolicy");
+ }
}
+ /**
+ * Removes old rule instances whose owner is not installed.
+ */
+ private void cleanUpZenRules() {
+ long currentTime = System.currentTimeMillis();
+ synchronized (mConfig) {
+ final ZenModeConfig newConfig = mConfig.copy();
+ if (newConfig.automaticRules != null) {
+ for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
+ ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
+ if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
+ try {
+ mPm.getPackageInfo(rule.component.getPackageName(), 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ newConfig.automaticRules.removeAt(i);
+ }
+ }
+ }
+ }
+ setConfig(newConfig, "cleanUpZenRules");
+ }
+ }
+
+ /**
+ * @return a copy of the zen mode configuration
+ */
public ZenModeConfig getConfig() {
synchronized (mConfig) {
return mConfig.copy();
@@ -517,19 +558,17 @@
return true;
}
mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config
- synchronized (mConfig) {
- mConfigs.put(config.user, config);
- if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable());
- ZenLog.traceConfig(reason, mConfig, config);
- final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
- getNotificationPolicy(config));
- mConfig = config;
- if (config.equals(mConfig)) {
- dispatchOnConfigChanged();
- }
- if (policyChanged) {
- dispatchOnPolicyChanged();
- }
+ mConfigs.put(config.user, config);
+ if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable());
+ ZenLog.traceConfig(reason, mConfig, config);
+ final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
+ getNotificationPolicy(config));
+ mConfig = config;
+ if (config.equals(mConfig)) {
+ dispatchOnConfigChanged();
+ }
+ if (policyChanged) {
+ dispatchOnPolicyChanged();
}
final String val = Integer.toString(config.hashCode());
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
@@ -994,7 +1033,9 @@
break;
case MSG_SET_CONFIG:
ConfigMessageData configData = (ConfigMessageData)msg.obj;
- setConfig(configData.config, configData.reason);
+ synchronized (mConfig) {
+ setConfig(configData.config, configData.reason);
+ }
break;
}
}