Merge changes I1149cb5b,Ib89a17aa
* changes: Allow condition providers to specify a rule instance limit. Verify zen rule owners before persisting rules.
This commit is contained in:
committed by
Android (Google) Code Review
commit
f4fb94ceab
@@ -33620,6 +33620,7 @@ package android.service.notification {
|
||||
method public abstract void onUnsubscribe(android.net.Uri);
|
||||
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
|
||||
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
|
||||
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
|
||||
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
|
||||
}
|
||||
|
||||
@@ -35766,6 +35766,7 @@ package android.service.notification {
|
||||
method public abstract void onUnsubscribe(android.net.Uri);
|
||||
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
|
||||
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
|
||||
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
|
||||
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
|
||||
}
|
||||
|
||||
@@ -33634,6 +33634,7 @@ package android.service.notification {
|
||||
method public abstract void onUnsubscribe(android.net.Uri);
|
||||
field public static final java.lang.String EXTRA_RULE_ID = "android.content.automatic.ruleId";
|
||||
field public static final java.lang.String META_DATA_CONFIGURATION_ACTIVITY = "android.service.zen.automatic.configurationActivity";
|
||||
field public static final java.lang.String META_DATA_RULE_INSTANCE_LIMIT = "android.service.zen.automatic.ruleInstanceLimit";
|
||||
field public static final java.lang.String META_DATA_RULE_TYPE = "android.service.zen.automatic.ruleType";
|
||||
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.ConditionProviderService";
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ interface INotificationManager
|
||||
boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
|
||||
boolean removeAutomaticZenRule(String id);
|
||||
boolean removeAutomaticZenRules(String packageName);
|
||||
int getRuleInstanceCount(in ComponentName owner);
|
||||
|
||||
byte[] getBackupPayload(int user);
|
||||
void applyRestore(in byte[] payload, int user);
|
||||
|
||||
@@ -379,6 +379,18 @@ public class NotificationManager
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int getRuleInstanceCount(ComponentName owner) {
|
||||
INotificationManager service = getService();
|
||||
try {
|
||||
return service.getRuleInstanceCount(owner);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns AutomaticZenRules owned by the caller.
|
||||
*
|
||||
|
||||
@@ -84,6 +84,13 @@ public abstract class ConditionProviderService extends Service {
|
||||
public static final String META_DATA_CONFIGURATION_ACTIVITY =
|
||||
"android.service.zen.automatic.configurationActivity";
|
||||
|
||||
/**
|
||||
* The name of the {@code meta-data} tag containing the maximum number of rule instances that
|
||||
* can be created for this rule type. Omit or enter a value <= 0 to allow unlimited instances.
|
||||
*/
|
||||
public static final String META_DATA_RULE_INSTANCE_LIMIT =
|
||||
"android.service.zen.automatic.ruleInstanceLimit";
|
||||
|
||||
/**
|
||||
* A String rule id extra passed to {@link #META_DATA_CONFIGURATION_ACTIVITY}.
|
||||
*/
|
||||
|
||||
@@ -1726,6 +1726,14 @@ public class NotificationManagerService extends SystemService {
|
||||
return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRuleInstanceCount(ComponentName owner) throws RemoteException {
|
||||
Preconditions.checkNotNull(owner, "Owner is null");
|
||||
enforceSystemOrSystemUI("getRuleInstanceCount");
|
||||
|
||||
return mZenModeHelper.getCurrentInstanceCount(owner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
|
||||
enforcePolicyAccess(pkg, "setInterruptionFilter");
|
||||
|
||||
@@ -27,7 +27,10 @@ import android.app.NotificationManager.Policy;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.database.ContentObserver;
|
||||
@@ -45,7 +48,7 @@ import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings.Global;
|
||||
import android.service.notification.IConditionListener;
|
||||
import android.service.notification.ConditionProviderService;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.service.notification.ZenModeConfig.EventInfo;
|
||||
import android.service.notification.ZenModeConfig.ScheduleInfo;
|
||||
@@ -91,6 +94,7 @@ public class ZenModeHelper {
|
||||
private final ZenModeConditions mConditions;
|
||||
private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
|
||||
private final Metrics mMetrics = new Metrics();
|
||||
private final ConditionProviders.Config mServiceConfig;
|
||||
|
||||
private int mZenMode;
|
||||
private int mUser = UserHandle.USER_SYSTEM;
|
||||
@@ -113,6 +117,7 @@ public class ZenModeHelper {
|
||||
mSettingsObserver.observe();
|
||||
mFiltering = new ZenModeFiltering(mContext);
|
||||
mConditions = new ZenModeConditions(this, conditionProviders);
|
||||
mServiceConfig = conditionProviders.getConfig();
|
||||
}
|
||||
|
||||
public Looper getLooper() {
|
||||
@@ -197,7 +202,7 @@ public class ZenModeHelper {
|
||||
config.user = user;
|
||||
}
|
||||
synchronized (mConfig) {
|
||||
setConfig(config, "onUserSwitched");
|
||||
setConfigLocked(config, "onUserSwitched");
|
||||
}
|
||||
cleanUpZenRules();
|
||||
}
|
||||
@@ -257,22 +262,34 @@ public class ZenModeHelper {
|
||||
}
|
||||
|
||||
public AutomaticZenRule addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
|
||||
if (!TextUtils.isEmpty(automaticZenRule.getId())) {
|
||||
throw new IllegalArgumentException("Rule already exists");
|
||||
}
|
||||
if (!isSystemRule(automaticZenRule)) {
|
||||
ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
|
||||
if (owner == null) {
|
||||
throw new IllegalArgumentException("Owner is not a condition provider service");
|
||||
}
|
||||
|
||||
final int ruleInstanceLimit = owner.metaData.getInt(
|
||||
ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
|
||||
if (ruleInstanceLimit > 0 && ruleInstanceLimit
|
||||
< (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
|
||||
throw new IllegalArgumentException("Rule instance limit exceeded");
|
||||
}
|
||||
}
|
||||
|
||||
ZenModeConfig newConfig;
|
||||
synchronized (mConfig) {
|
||||
if (mConfig == null) return null;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG,
|
||||
"addAutomaticZenRule zenRule= " + automaticZenRule + " reason=" + reason);
|
||||
}
|
||||
if (!TextUtils.isEmpty(automaticZenRule.getId())) {
|
||||
throw new IllegalArgumentException("Rule already exists");
|
||||
Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
|
||||
}
|
||||
newConfig = mConfig.copy();
|
||||
|
||||
ZenRule rule = new ZenRule();
|
||||
populateZenRule(automaticZenRule, rule, true);
|
||||
newConfig.automaticRules.put(rule.id, rule);
|
||||
if (setConfig(newConfig, reason, true)) {
|
||||
if (setConfigLocked(newConfig, reason, true)) {
|
||||
return createAutomaticZenRule(rule);
|
||||
} else {
|
||||
return null;
|
||||
@@ -302,7 +319,7 @@ public class ZenModeHelper {
|
||||
}
|
||||
populateZenRule(automaticZenRule, rule, false);
|
||||
newConfig.automaticRules.put(ruleId, rule);
|
||||
return setConfig(newConfig, reason, true);
|
||||
return setConfigLocked(newConfig, reason, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +337,7 @@ public class ZenModeHelper {
|
||||
throw new SecurityException(
|
||||
"Cannot delete rules not owned by your condition provider");
|
||||
}
|
||||
return setConfig(newConfig, reason, true);
|
||||
return setConfigLocked(newConfig, reason, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,10 +353,22 @@ public class ZenModeHelper {
|
||||
newConfig.automaticRules.removeAt(i);
|
||||
}
|
||||
}
|
||||
return setConfig(newConfig, reason, true);
|
||||
return setConfigLocked(newConfig, reason, true);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentInstanceCount(ComponentName owner) {
|
||||
int count = 0;
|
||||
synchronized (mConfig) {
|
||||
for (ZenRule rule : mConfig.automaticRules.values()) {
|
||||
if (rule.component != null && rule.component.equals(owner)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean canManageAutomaticZenRule(ZenRule rule) {
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
|
||||
@@ -361,6 +390,29 @@ public class ZenModeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSystemRule(AutomaticZenRule rule) {
|
||||
return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
|
||||
}
|
||||
|
||||
private ServiceInfo getServiceInfo(ComponentName owner) {
|
||||
Intent queryIntent = new Intent();
|
||||
queryIntent.setComponent(owner);
|
||||
List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
|
||||
queryIntent,
|
||||
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
|
||||
UserHandle.getCallingUserId());
|
||||
if (installedServices != null) {
|
||||
for (int i = 0, count = installedServices.size(); i < count; i++) {
|
||||
ResolveInfo resolveInfo = installedServices.get(i);
|
||||
ServiceInfo info = resolveInfo.serviceInfo;
|
||||
if (mServiceConfig.bindPermission.equals(info.permission)) {
|
||||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
|
||||
if (isNew) {
|
||||
rule.id = ZenModeConfig.newRuleId();
|
||||
@@ -413,7 +465,7 @@ public class ZenModeHelper {
|
||||
newRule.conditionId = conditionId;
|
||||
newConfig.manualRule = newRule;
|
||||
}
|
||||
setConfig(newConfig, reason, setRingerMode);
|
||||
setConfigLocked(newConfig, reason, setRingerMode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,7 +530,7 @@ public class ZenModeHelper {
|
||||
}
|
||||
if (DEBUG) Log.d(TAG, "readXml");
|
||||
synchronized (mConfig) {
|
||||
setConfig(config, "readXml");
|
||||
setConfigLocked(config, "readXml");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,7 +559,7 @@ public class ZenModeHelper {
|
||||
synchronized (mConfig) {
|
||||
final ZenModeConfig newConfig = mConfig.copy();
|
||||
newConfig.applyNotificationPolicy(policy);
|
||||
setConfig(newConfig, "setNotificationPolicy");
|
||||
setConfigLocked(newConfig, "setNotificationPolicy");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,7 +582,7 @@ public class ZenModeHelper {
|
||||
}
|
||||
}
|
||||
}
|
||||
setConfig(newConfig, "cleanUpZenRules");
|
||||
setConfigLocked(newConfig, "cleanUpZenRules");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,30 +595,30 @@ public class ZenModeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean setConfig(ZenModeConfig config, String reason) {
|
||||
return setConfig(config, reason, true /*setRingerMode*/);
|
||||
public boolean setConfigLocked(ZenModeConfig config, String reason) {
|
||||
return setConfigLocked(config, reason, true /*setRingerMode*/);
|
||||
}
|
||||
|
||||
public void setConfigAsync(ZenModeConfig config, String reason) {
|
||||
mHandler.postSetConfig(config, reason);
|
||||
}
|
||||
|
||||
private boolean setConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
|
||||
private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
if (config == null || !config.isValid()) {
|
||||
Log.w(TAG, "Invalid config in setConfig; " + config);
|
||||
Log.w(TAG, "Invalid config in setConfigLocked; " + config);
|
||||
return false;
|
||||
}
|
||||
if (config.user != mUser) {
|
||||
// simply store away for background users
|
||||
mConfigs.put(config.user, config);
|
||||
if (DEBUG) Log.d(TAG, "setConfig: store config for user " + config.user);
|
||||
if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
|
||||
return true;
|
||||
}
|
||||
mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config
|
||||
mConfigs.put(config.user, config);
|
||||
if (DEBUG) Log.d(TAG, "setConfig reason=" + reason, new Throwable());
|
||||
if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
|
||||
ZenLog.traceConfig(reason, mConfig, config);
|
||||
final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
|
||||
getNotificationPolicy(config));
|
||||
@@ -1041,7 +1093,7 @@ public class ZenModeHelper {
|
||||
case MSG_SET_CONFIG:
|
||||
ConfigMessageData configData = (ConfigMessageData)msg.obj;
|
||||
synchronized (mConfig) {
|
||||
setConfig(configData.config, configData.reason);
|
||||
setConfigLocked(configData.config, configData.reason);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user