diff --git a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java index d0f1ee69efa..1499656eacf 100644 --- a/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java +++ b/src/com/android/settings/notification/AbstractZenModeAutomaticRulePreferenceController.java @@ -21,6 +21,8 @@ import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ComponentInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.provider.Settings; @@ -82,33 +84,47 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends return intent; } - public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) { - if (si == null || si.metaData == null) { + public static ZenRuleInfo getRuleInfo(PackageManager pm, ComponentInfo ci) { + if (ci == null || ci.metaData == null) { return null; } - final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE); - final ComponentName configurationActivity = getSettingsActivity(si); + final String ruleType = (ci instanceof ServiceInfo) + ? ci.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE) + : ci.metaData.getString(NotificationManager.META_DATA_AUTOMATIC_RULE_TYPE); + + final ComponentName configurationActivity = getSettingsActivity(null, ci); if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) { final ZenRuleInfo ri = new ZenRuleInfo(); - ri.serviceComponent = new ComponentName(si.packageName, si.name); + ri.serviceComponent = + (ci instanceof ServiceInfo) ? new ComponentName(ci.packageName, ci.name) : null; ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS; ri.title = ruleType; - ri.packageName = si.packageName; - ri.configurationActivity = getSettingsActivity(si); - ri.packageLabel = si.applicationInfo.loadLabel(pm); - ri.ruleInstanceLimit = - si.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); + ri.packageName = ci.packageName; + ri.configurationActivity = configurationActivity; + ri.packageLabel = ci.applicationInfo.loadLabel(pm); + ri.ruleInstanceLimit = (ci instanceof ServiceInfo) + ? ci.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1) + : ci.metaData.getInt(NotificationManager.META_DATA_RULE_INSTANCE_LIMIT, -1); return ri; } return null; } - protected static ComponentName getSettingsActivity(ServiceInfo si) { - if (si == null || si.metaData == null) { + protected static ComponentName getSettingsActivity(AutomaticZenRule rule, ComponentInfo ci) { + // prefer config activity on the rule itself; fallback to manifest definition + if (rule != null && rule.getConfigurationActivity() != null) { + return rule.getConfigurationActivity(); + } + if (ci == null) { return null; } + // new activity backed rule + if (ci instanceof ActivityInfo) { + return new ComponentName(ci.packageName, ci.name); + } + // old service backed rule final String configurationActivity = - si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY); + ci.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY); if (configurationActivity != null) { return ComponentName.unflattenFromString(configurationActivity); } @@ -127,7 +143,7 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK); AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent, - mRuleInfo.defaultConditionId, + mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null, NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); String savedRuleId = mBackend.addZenRule(rule); if (savedRuleId != null) { diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java index d6a7d72e0cb..57ee545292b 100644 --- a/src/com/android/settings/notification/ZenModeAutomationSettings.java +++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java @@ -18,6 +18,7 @@ package com.android.settings.notification; import android.app.AlertDialog; import android.app.AutomaticZenRule; +import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; @@ -92,6 +93,7 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { return new ManagedServiceSettings.Config.Builder() .setTag(TAG) .setIntentAction(ConditionProviderService.SERVICE_INTERFACE) + .setConfigurationIntentAction(NotificationManager.ACTION_AUTOMATIC_ZEN_RULE) .setPermission(android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE) .setNoun("condition provider") .build(); diff --git a/src/com/android/settings/notification/ZenRuleInfo.java b/src/com/android/settings/notification/ZenRuleInfo.java index 2d7abf81bce..1a1539b6a3d 100644 --- a/src/com/android/settings/notification/ZenRuleInfo.java +++ b/src/com/android/settings/notification/ZenRuleInfo.java @@ -24,6 +24,8 @@ public class ZenRuleInfo { that.defaultConditionId) : that.defaultConditionId != null) return false; if (serviceComponent != null ? !serviceComponent.equals( that.serviceComponent) : that.serviceComponent != null) return false; + if (id != null ? !id.equals(that.id) : that.id != null) + return false; return packageLabel != null ? packageLabel.equals( that.packageLabel) : that.packageLabel == null; @@ -38,4 +40,5 @@ public class ZenRuleInfo { public boolean isSystem; public CharSequence packageLabel; public int ruleInstanceLimit = -1; + public String id; } diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java index 10b49eb73dd..91f68e824a7 100644 --- a/src/com/android/settings/notification/ZenRulePreference.java +++ b/src/com/android/settings/notification/ZenRulePreference.java @@ -21,6 +21,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.service.notification.ZenModeConfig; @@ -45,7 +46,6 @@ public class ZenRulePreference extends TwoTargetPreference { private static final ManagedServiceSettings.Config CONFIG = ZenModeAutomationSettings.getConditionProviderConfig(); final String mId; - boolean appExists; final Fragment mParent; final Preference mPref; final Context mContext; @@ -56,7 +56,6 @@ public class ZenRulePreference extends TwoTargetPreference { final AutomaticZenRule mRule; CharSequence mName; - private boolean mIsSystemRule; private Intent mIntent; private boolean mChecked; private CheckBox mCheckBox; @@ -163,25 +162,17 @@ public class ZenRulePreference extends TwoTargetPreference { final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId( rule.getConditionId(), true); final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId()); - mIsSystemRule = isSchedule || isEvent; - try { - ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0); - setSummary(computeRuleSummary(rule)); - } catch (PackageManager.NameNotFoundException e) { - appExists = false; - return; - } + setSummary(computeRuleSummary(rule)); - appExists = true; setTitle(mName); setPersistent(false); final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION : isEvent ? ZenModeEventRuleSettings.ACTION : ""; - ServiceInfo si = mServiceListing.findService(rule.getOwner()); + ComponentInfo si = mServiceListing.findService(rule.getOwner()); ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController. - getSettingsActivity(si); + getSettingsActivity(rule, si); mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action, settingsActivity, mId); setKey(mId); diff --git a/src/com/android/settings/notification/ZenRuleSelectionDialog.java b/src/com/android/settings/notification/ZenRuleSelectionDialog.java index abda3769be8..7f0b4c2dff6 100644 --- a/src/com/android/settings/notification/ZenRuleSelectionDialog.java +++ b/src/com/android/settings/notification/ZenRuleSelectionDialog.java @@ -23,6 +23,7 @@ import android.app.NotificationManager; import android.content.Context; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; +import android.content.pm.ComponentInfo; import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.graphics.drawable.Drawable; @@ -192,16 +193,17 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment { private final ZenServiceListing.Callback mServiceListingCallback = new ZenServiceListing.Callback() { @Override - public void onServicesReloaded(Set services) { - if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size()); + public void onComponentsReloaded(Set componentInfos) { + if (DEBUG) Log.d(TAG, "Reloaded: count=" + componentInfos.size()); + Set externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR); - for (ServiceInfo serviceInfo : services) { + for (ComponentInfo ci : componentInfos) { final ZenRuleInfo ri = AbstractZenModeAutomaticRulePreferenceController. - getRuleInfo(mPm, serviceInfo); + getRuleInfo(mPm, ci); if (ri != null && ri.configurationActivity != null && mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName) && (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit - >= (mNm.getRuleInstanceCount(serviceInfo.getComponentName()) + 1))) { + >= (mNm.getRuleInstanceCount(ci.getComponentName()) + 1))) { externalRuleTypes.add(ri); } } diff --git a/src/com/android/settings/utils/ManagedServiceSettings.java b/src/com/android/settings/utils/ManagedServiceSettings.java index e5dfb066e3e..16f79c2aebe 100644 --- a/src/com/android/settings/utils/ManagedServiceSettings.java +++ b/src/com/android/settings/utils/ManagedServiceSettings.java @@ -240,9 +240,11 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { public final int warningDialogTitle; public final int warningDialogSummary; public final int emptyText; + public final String configIntentAction; - private Config(String tag, String setting, String intentAction, String permission, - String noun, int warningDialogTitle, int warningDialogSummary, int emptyText) { + private Config(String tag, String setting, String intentAction, String configIntentAction, + String permission, String noun, int warningDialogTitle, int warningDialogSummary, + int emptyText) { this.tag = tag; this.setting = setting; this.intentAction = intentAction; @@ -251,6 +253,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { this.warningDialogTitle = warningDialogTitle; this.warningDialogSummary = warningDialogSummary; this.emptyText = emptyText; + this.configIntentAction = configIntentAction; } public static class Builder{ @@ -262,6 +265,7 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { private int mWarningDialogTitle; private int mWarningDialogSummary; private int mEmptyText; + private String mConfigIntentAction; public Builder setTag(String tag) { mTag = tag; @@ -278,6 +282,11 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { return this; } + public Builder setConfigurationIntentAction(String action) { + mConfigIntentAction = action; + return this; + } + public Builder setPermission(String permission) { mPermission = permission; return this; @@ -304,8 +313,8 @@ public abstract class ManagedServiceSettings extends EmptyTextSettings { } public Config build() { - return new Config(mTag, mSetting, mIntentAction, mPermission, mNoun, - mWarningDialogTitle, mWarningDialogSummary, mEmptyText); + return new Config(mTag, mSetting, mIntentAction, mConfigIntentAction, mPermission, + mNoun, mWarningDialogTitle, mWarningDialogSummary, mEmptyText); } } } diff --git a/src/com/android/settings/utils/ZenServiceListing.java b/src/com/android/settings/utils/ZenServiceListing.java index e87cc51f2c2..99f56f621c8 100644 --- a/src/com/android/settings/utils/ZenServiceListing.java +++ b/src/com/android/settings/utils/ZenServiceListing.java @@ -20,6 +20,8 @@ import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.ComponentInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -34,7 +36,7 @@ public class ZenServiceListing { private final Context mContext; private final ManagedServiceSettings.Config mConfig; - private final Set mApprovedServices = new ArraySet(); + private final Set mApprovedComponents = new ArraySet<>(); private final List mZenCallbacks = new ArrayList<>(); private final NotificationManager mNm; @@ -44,11 +46,14 @@ public class ZenServiceListing { mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); } - public ServiceInfo findService(final ComponentName cn) { - for (ServiceInfo service : mApprovedServices) { - final ComponentName serviceCN = new ComponentName(service.packageName, service.name); - if (serviceCN.equals(cn)) { - return service; + public ComponentInfo findService(final ComponentName cn) { + if (cn == null) { + return null; + } + for (ComponentInfo component : mApprovedComponents) { + final ComponentName ci = new ComponentName(component.packageName, component.name); + if (ci.equals(cn)) { + return component; } } return null; @@ -63,32 +68,29 @@ public class ZenServiceListing { } public void reloadApprovedServices() { - mApprovedServices.clear(); + mApprovedComponents.clear(); List enabledNotificationListenerPkgs = mNm.getEnabledNotificationListenerPackages(); - List services = new ArrayList<>(); - getServices(mConfig, services, mContext.getPackageManager()); - for (ServiceInfo service : services) { - final String servicePackage = service.getComponentName().getPackageName(); - if (mNm.isNotificationPolicyAccessGrantedForPackage(servicePackage) - || enabledNotificationListenerPkgs.contains(servicePackage)) { - mApprovedServices.add(service); + List components = new ArrayList<>(); + getServices(mConfig, components, mContext.getPackageManager()); + getActivities(mConfig, components, mContext.getPackageManager()); + for (ComponentInfo componentInfo : components) { + final String pkg = componentInfo.getComponentName().getPackageName(); + if (mNm.isNotificationPolicyAccessGrantedForPackage(pkg) + || enabledNotificationListenerPkgs.contains(pkg)) { + mApprovedComponents.add(componentInfo); } } - if (!mApprovedServices.isEmpty()) { + if (!mApprovedComponents.isEmpty()) { for (Callback callback : mZenCallbacks) { - callback.onServicesReloaded(mApprovedServices); + callback.onComponentsReloaded(mApprovedComponents); } } } - private static int getServices(ManagedServiceSettings.Config c, List list, + private static void getServices(ManagedServiceSettings.Config c, List list, PackageManager pm) { - int services = 0; - if (list != null) { - list.clear(); - } final int user = ActivityManager.getCurrentUser(); List installedServices = pm.queryIntentServicesAsUser( @@ -110,12 +112,28 @@ public class ZenServiceListing { if (list != null) { list.add(info); } - services++; } - return services; + } + + private static void getActivities(ManagedServiceSettings.Config c, List list, + PackageManager pm) { + final int user = ActivityManager.getCurrentUser(); + + List resolveInfos = pm.queryIntentActivitiesAsUser( + new Intent(c.configIntentAction), + PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA, + user); + + for (int i = 0, count = resolveInfos.size(); i < count; i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + ActivityInfo info = resolveInfo.activityInfo; + if (list != null) { + list.add(info); + } + } } public interface Callback { - void onServicesReloaded(Set services); + void onComponentsReloaded(Set components); } } diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java index 5e3d6e9888c..41227c5349e 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceControllerTest.java @@ -83,12 +83,12 @@ public class ZenModeAutomaticRulesPreferenceControllerTest { String ruleId2 = "test2_id"; String ruleId3 = "test3_id"; - AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); - AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20); - AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30); + AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); + AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20); + AutomaticZenRule autoRule3 = new AutomaticZenRule("test_rule_3", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 30); rMap.put(ruleId1, autoRule1); rMap.put(ruleId2, autoRule2); @@ -109,10 +109,10 @@ public class ZenModeAutomaticRulesPreferenceControllerTest { String ruleId1 = "test1_id"; String ruleId2 = "test2_id"; - AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); - AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20); + AutomaticZenRule autoRule1 = new AutomaticZenRule("test_rule_1", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); + AutomaticZenRule autoRule2 = new AutomaticZenRule("test_rule_2", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20); rMap.put(ruleId1, autoRule1); rMap.put(ruleId2, autoRule2); @@ -130,8 +130,8 @@ public class ZenModeAutomaticRulesPreferenceControllerTest { final int NUM_RULES = 1; Map rMap = new HashMap<>(); String testId = "test1_id"; - AutomaticZenRule rule = new AutomaticZenRule("rule_name", null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); + AutomaticZenRule rule = new AutomaticZenRule("rule_name", null, null, + null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10); rMap.put(testId, rule); when(mockPref.getPreferenceCount()).thenReturn(NUM_RULES); diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java index 3feff0d28b2..6169f92ddc9 100644 --- a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java +++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java @@ -69,13 +69,14 @@ public class ZenModeBackendTest { for (int i = 0; i < numRules; i++) { ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2)); + null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, + i * 2)); } if (addDefaultRules) { - ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, + ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20)); - ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, + ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10)); } @@ -90,13 +91,14 @@ public class ZenModeBackendTest { for (int i = 0; i < numRules; i++) { ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null, - null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i)); + null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, + numRules - i)); } if (addDefaultRules) { - ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, + ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null, null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10)); - ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, + ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_2_NAME", null, null, null, null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20)); }