Added zen settings messages and calls preferences.

- Made ZenModeSettings and ZenModeBehaviorSettings a DashboardFragment
- Switches in ZenModeBehaviorSettings all have their own preference controllers
- Instead of a dropdown, messages & calls have their own pages & preference controllers
- Added basic turn on/off DND button in settings (dialog not yet implemented)

Bug: 63077372
Fixes: 69057767
Test: make -j40 RunSettingsRoboTests
Change-Id: I1c70f77053713f66f873ee578477f23cfd7985bb
This commit is contained in:
Beverly
2017-10-27 14:44:23 -04:00
parent a40f6a2a45
commit a58e52a0be
53 changed files with 3888 additions and 815 deletions

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.Fragment;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import android.service.notification.ConditionProviderService;
import android.service.notification.ZenModeConfig;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
abstract public class AbstractZenModeAutomaticRulePreferenceController extends
AbstractPreferenceController implements PreferenceControllerMixin {
private static final String TAG = "ZenModeAutomaticRule";
protected ZenModeBackend mBackend;
protected Fragment mParent;
protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
protected PackageManager mPm;
public AbstractZenModeAutomaticRulePreferenceController(Context context, Fragment parent) {
super(context);
mBackend = ZenModeBackend.getInstance(context);
mParent = parent;
mPm = mContext.getPackageManager();
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
mRules = getZenModeRules();
}
private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {
Map<String, AutomaticZenRule> ruleMap =
NotificationManager.from(mContext).getAutomaticZenRules();
return ruleMap.entrySet();
}
protected void showNameRuleDialog(final ZenRuleInfo ri) {
new ZenRuleNameDialog(mContext, null, ri.defaultConditionId) {
@Override
public void onOk(String ruleName) {
AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
true);
String savedRuleId = mBackend.addZenRule(rule);
if (savedRuleId != null) {
mParent.startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
}
}
}.show();
}
protected Map.Entry<String, AutomaticZenRule>[] sortedRules() {
if (mRules == null) {
mRules = getZenModeRules();
}
final Map.Entry<String, AutomaticZenRule>[] rt =
mRules.toArray(new Map.Entry[mRules.size()]);
Arrays.sort(rt, RULE_COMPARATOR);
return rt;
}
protected static Intent getRuleIntent(String settingsAction,
ComponentName configurationActivity, String ruleId) {
final Intent intent = new Intent()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
if (configurationActivity != null) {
intent.setComponent(configurationActivity);
} else {
intent.setAction(settingsAction);
}
return intent;
}
private static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
new Comparator<Map.Entry<String, AutomaticZenRule>>() {
@Override
public int compare(Map.Entry<String, AutomaticZenRule> lhs,
Map.Entry<String, AutomaticZenRule> rhs) {
int byDate = Long.compare(lhs.getValue().getCreationTime(),
rhs.getValue().getCreationTime());
if (byDate != 0) {
return byDate;
} else {
return key(lhs.getValue()).compareTo(key(rhs.getValue()));
}
}
private String key(AutomaticZenRule rule) {
final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
? 2 : 3;
return type + rule.getName().toString();
}
};
public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
if (si == null || si.metaData == null) {
return null;
}
final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
final ComponentName configurationActivity = getSettingsActivity(si);
if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
final ZenRuleInfo ri = new ZenRuleInfo();
ri.serviceComponent = new ComponentName(si.packageName, si.name);
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);
return ri;
}
return null;
}
protected static ComponentName getSettingsActivity(ServiceInfo si) {
if (si == null || si.metaData == null) {
return null;
}
final String configurationActivity =
si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
if (configurationActivity != null) {
return ComponentName.unflattenFromString(configurationActivity);
}
return null;
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
abstract public class AbstractZenModePreferenceController extends
AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver,
OnResume, OnPause {
private SettingObserver mSettingObserver;
private final String KEY;
final private NotificationManager mNotificationManager;
public AbstractZenModePreferenceController(Context context, String key,
Lifecycle lifecycle) {
super(context);
if (lifecycle != null) {
lifecycle.addObserver(this);
}
KEY = key;
mNotificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mSettingObserver = new SettingObserver(screen.findPreference(KEY));
}
@Override
public void onResume() {
if (mSettingObserver != null) {
mSettingObserver.register(mContext.getContentResolver());
}
}
@Override
public void onPause() {
if (mSettingObserver != null) {
mSettingObserver.unregister(mContext.getContentResolver());
}
}
protected NotificationManager.Policy getPolicy() {
return mNotificationManager.getNotificationPolicy();
}
protected int getZenMode() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ZEN_MODE, 0);
}
class SettingObserver extends ContentObserver {
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
Settings.Global.ZEN_MODE_CONFIG_ETAG);
private final Preference mPreference;
public SettingObserver(Preference preference) {
super(new Handler());
mPreference = preference;
}
public void register(ContentResolver cr) {
cr.registerContentObserver(ZEN_MODE_URI, false, this);
cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this);
}
public void unregister(ContentResolver cr) {
cr.unregisterContentObserver(this);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (ZEN_MODE_URI.equals(uri)) {
updateState(mPreference);
}
if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
updateState(mPreference);
}
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.utils.ZenServiceListing;
public class ZenModeAddAutomaticRulePreferenceController extends
AbstractZenModeAutomaticRulePreferenceController implements
Preference.OnPreferenceClickListener {
private final String KEY_ADD_RULE;
private final ZenServiceListing mZenServiceListing;
public ZenModeAddAutomaticRulePreferenceController(Context context, String key,
Fragment parent, ZenServiceListing serviceListing) {
super(context, parent);
KEY_ADD_RULE = key;
mZenServiceListing = serviceListing;
}
@Override
public String getPreferenceKey() {
return KEY_ADD_RULE;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
Preference pref = screen.findPreference(KEY_ADD_RULE);
pref.setPersistent(false);
pref.setOnPreferenceClickListener(this);
}
@Override
public boolean onPreferenceClick(Preference preference) {
new ZenRuleSelectionDialog(mContext, mZenServiceListing) {
@Override
public void onSystemRuleSelected(ZenRuleInfo ri) {
showNameRuleDialog(ri);
}
@Override
public void onExternalRuleSelected(ZenRuleInfo ri) {
Intent intent = new Intent().setComponent(ri.configurationActivity);
mParent.startActivity(intent);
}
}.show();
return true;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeAlarmsPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_alarms";
private final ZenModeBackend mBackend;
public ZenModeAlarmsPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
pref.setEnabled(false);
pref.setChecked(false);
break;
case Settings.Global.ZEN_MODE_ALARMS:
pref.setEnabled(false);
pref.setChecked(true);
break;
default:
pref.setEnabled(true);
pref.setChecked(mBackend.isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_ALARMS));
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowAlarms = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowAlarms=" + allowAlarms);
}
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_ALARMS, allowAlarms);
return true;
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.Fragment;
import android.content.Context;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import java.util.Map;
public class ZenModeAutomaticRulesPreferenceController extends
AbstractZenModeAutomaticRulePreferenceController {
private final String KEY_AUTOMATIC_RULES;
private PreferenceCategory mPreferenceCategory;
Map.Entry<String, AutomaticZenRule>[] mSortedRules;
public ZenModeAutomaticRulesPreferenceController(Context context, String key,
Fragment parent) {
super(context, parent);
KEY_AUTOMATIC_RULES = key;
mSortedRules = sortedRules();
}
@Override
public String getPreferenceKey() {
return KEY_AUTOMATIC_RULES;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
mPreferenceCategory.setPersistent(false);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
// no need to update AutomaticRule if a rule was deleted
// (on rule deletion, the preference removes itself from its parent)
int oldRuleLength = mSortedRules.length;
mSortedRules = sortedRules();
if (!wasRuleDeleted(oldRuleLength)) {
updateAutomaticRules();
}
}
private boolean wasRuleDeleted(int oldRuleLength) {
int newRuleLength = mSortedRules.length;
int prefCount = mPreferenceCategory.getPreferenceCount();
return (prefCount == oldRuleLength -1) && (prefCount == newRuleLength);
}
private void updateAutomaticRules() {
for (Map.Entry<String, AutomaticZenRule> sortedRule : mSortedRules) {
ZenRulePreference currPref = (ZenRulePreference)
mPreferenceCategory.findPreference(sortedRule.getKey());
if (currPref != null && currPref.appExists) {
// rule already exists in preferences, update it
currPref.setAttributes(sortedRule.getValue());
} else {
// rule doesn't exist in preferences, add it
ZenRulePreference pref = new ZenRulePreference(mPreferenceCategory.getContext(),
sortedRule, mPreferenceCategory);
if (pref.appExists) {
mPreferenceCategory.addPreference(pref);
}
}
}
}
}

View File

@@ -0,0 +1,34 @@
package com.android.settings.notification;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
public class ZenModeAutomationPreferenceController extends
AbstractPreferenceController implements PreferenceControllerMixin {
protected static final String KEY_ZEN_MODE_AUTOMATION = "zen_mode_automation_settings";
private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModeAutomationPreferenceController(Context context) {
super(context);
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
public String getPreferenceKey() {
return KEY_ZEN_MODE_AUTOMATION;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
preference.setSummary(mSummaryBuilder.getAutomaticRulesSummary());
}
}

View File

@@ -16,167 +16,47 @@
package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.service.notification.ConditionProviderService;
import android.service.notification.ZenModeConfig;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.PreferenceViewHolder;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.utils.ManagedServiceSettings.Config;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
import com.android.settingslib.TwoTargetPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Arrays;
import java.util.Comparator;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ZenModeAutomationSettings extends ZenModeSettingsBase implements Indexable {
static final Config CONFIG = getConditionProviderConfig();
private PackageManager mPm;
private ZenServiceListing mServiceListing;
public class ZenModeAutomationSettings extends ZenModeSettingsBase {
private static final String KEY_ADD_RULE = "zen_mode_add_automatic_rule";
private static final String KEY_AUTOMATIC_RULES = "zen_mode_automatic_rules";
protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
addPreferencesFromResource(R.xml.zen_mode_automation_settings);
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
ZenServiceListing serviceListing = new ZenServiceListing(getContext(), CONFIG);
serviceListing.reloadApprovedServices();
return buildPreferenceControllers(context, this, serviceListing);
}
mPm = mContext.getPackageManager();
mServiceListing = new ZenServiceListing(mContext, CONFIG);
mServiceListing.reloadApprovedServices();
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Fragment parent, ZenServiceListing serviceListing) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeAddAutomaticRulePreferenceController(context, KEY_ADD_RULE,
parent, serviceListing));
controllers.add(new ZenModeAutomaticRulesPreferenceController(context,
KEY_AUTOMATIC_RULES, parent));
return controllers;
}
@Override
protected void onZenModeChanged() {
// don't care
}
@Override
protected void onZenModeConfigChanged() {
updateControls();
}
@Override
public void onResume() {
super.onResume();
if (isUiRestricted()) {
return;
}
updateControls();
}
private void showAddRuleDialog() {
new ZenRuleSelectionDialog(mContext, mServiceListing) {
@Override
public void onSystemRuleSelected(ZenRuleInfo ri) {
showNameRuleDialog(ri);
}
@Override
public void onExternalRuleSelected(ZenRuleInfo ri) {
Intent intent = new Intent().setComponent(ri.configurationActivity);
startActivity(intent);
}
}.show();
}
private void showNameRuleDialog(final ZenRuleInfo ri) {
new ZenRuleNameDialog(mContext, null, ri.defaultConditionId) {
@Override
public void onOk(String ruleName) {
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE_OK);
AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
true);
String savedRuleId = addZenRule(rule);
if (savedRuleId != null) {
startActivity(getRuleIntent(ri.settingsAction, null, savedRuleId));
}
}
}.show();
}
private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName) {
new AlertDialog.Builder(mContext)
.setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_delete_rule_button,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
removeZenRule(ruleId);
}
})
.show();
}
private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
String ruleId) {
final Intent intent = new Intent()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
if (configurationActivity != null) {
intent.setComponent(configurationActivity);
} else {
intent.setAction(settingsAction);
}
return intent;
}
private Map.Entry<String,AutomaticZenRule>[] sortedRules() {
final Map.Entry<String,AutomaticZenRule>[] rt =
mRules.toArray(new Map.Entry[mRules.size()]);
Arrays.sort(rt, RULE_COMPARATOR);
return rt;
}
private void updateControls() {
final PreferenceScreen root = getPreferenceScreen();
root.removeAll();
final Map.Entry<String,AutomaticZenRule>[] sortedRules = sortedRules();
for (Map.Entry<String,AutomaticZenRule> sortedRule : sortedRules) {
ZenRulePreference pref = new ZenRulePreference(getPrefContext(), sortedRule);
if (pref.appExists) {
root.addPreference(pref);
}
}
final Preference p = new Preference(getPrefContext());
p.setIcon(R.drawable.ic_menu_add);
p.setTitle(R.string.zen_mode_add_rule);
p.setPersistent(false);
p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ADD_RULE);
showAddRuleDialog();
return true;
}
});
root.addPreference(p);
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_automation_settings;
}
@Override
@@ -184,18 +64,8 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase implements In
return MetricsEvent.NOTIFICATION_ZEN_MODE_AUTOMATION;
}
private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
CharSequence providerLabel) {
final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
final String ruleState = (rule == null || !rule.isEnabled())
? getString(R.string.switch_off_text)
: getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
return ruleState;
}
private static Config getConditionProviderConfig() {
final Config c = new Config();
protected static ManagedServiceSettings.Config getConditionProviderConfig() {
final ManagedServiceSettings.Config c = new ManagedServiceSettings.Config();
c.tag = TAG;
c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
@@ -203,146 +73,22 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase implements In
return c;
}
private static String computeZenModeCaption(Resources res, int zenMode) {
switch (zenMode) {
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
return res.getString(R.string.zen_mode_option_alarms);
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
return res.getString(R.string.zen_mode_option_important_interruptions);
case NotificationManager.INTERRUPTION_FILTER_NONE:
return res.getString(R.string.zen_mode_option_no_interruptions);
default:
return null;
}
}
public static ZenRuleInfo getRuleInfo(PackageManager pm, ServiceInfo si) {
if (si == null || si.metaData == null) {
return null;
}
final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
final ComponentName configurationActivity = getSettingsActivity(si);
if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
final ZenRuleInfo ri = new ZenRuleInfo();
ri.serviceComponent = new ComponentName(si.packageName, si.name);
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);
return ri;
}
return null;
}
private static ComponentName getSettingsActivity(ServiceInfo si) {
if (si == null || si.metaData == null) {
return null;
}
final String configurationActivity =
si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
if (configurationActivity != null) {
return ComponentName.unflattenFromString(configurationActivity);
}
return null;
}
private static final Comparator<Map.Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
new Comparator<Map.Entry<String,AutomaticZenRule>>() {
@Override
public int compare(Map.Entry<String,AutomaticZenRule> lhs,
Map.Entry<String,AutomaticZenRule> rhs) {
int byDate = Long.compare(lhs.getValue().getCreationTime(),
rhs.getValue().getCreationTime());
if (byDate != 0) {
return byDate;
} else {
return key(lhs.getValue()).compareTo(key(rhs.getValue()));
}
}
private String key(AutomaticZenRule rule) {
final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
? 1 : ZenModeConfig.isValidEventConditionId(rule.getConditionId())
? 2 : 3;
return type + rule.getName().toString();
}
};
private class ZenRulePreference extends TwoTargetPreference {
final CharSequence mName;
final String mId;
final boolean appExists;
public ZenRulePreference(Context context,
final Map.Entry<String, AutomaticZenRule> ruleEntry) {
super(context);
final AutomaticZenRule rule = ruleEntry.getValue();
mName = rule.getName();
mId = ruleEntry.getKey();
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
rule.getConditionId());
final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
final boolean isSystemRule = isSchedule || isEvent;
try {
ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
} catch (PackageManager.NameNotFoundException e) {
appExists = false;
return;
}
appExists = true;
setTitle(rule.getName());
setPersistent(false);
final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
: isEvent ? ZenModeEventRuleSettings.ACTION : "";
ServiceInfo si = mServiceListing.findService(rule.getOwner());
ComponentName settingsActivity = getSettingsActivity(si);
setIntent(getRuleIntent(action, settingsActivity, mId));
setSelectable(settingsActivity != null || isSystemRule);
}
@Override
protected int getSecondTargetResId() {
return R.layout.zen_rule_widget;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
View v = view.findViewById(R.id.delete_zen_rule);
if (v != null) {
v.setOnClickListener(mDeleteListener);
}
}
private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
showDeleteRuleDialog(mId, mName);
}
};
}
/**
* For Search.
*/
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_automation_settings;
return Arrays.asList(sir);
}
};
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_ADD_RULE);
keys.add(KEY_AUTOMATIC_RULES);
return keys;
}
@Override
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null, null);
}
};
}

View File

@@ -0,0 +1,274 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.settings.R;
public class ZenModeBackend {
@VisibleForTesting
protected static final String ZEN_MODE_FROM_ANYONE = "zen_mode_from_anyone";
@VisibleForTesting
protected static final String ZEN_MODE_FROM_CONTACTS = "zen_mode_from_contacts";
@VisibleForTesting
protected static final String ZEN_MODE_FROM_STARRED = "zen_mode_from_starred";
@VisibleForTesting
protected static final String ZEN_MODE_FROM_NONE = "zen_mode_from_none";
protected static final int SOURCE_NONE = -1;
private static ZenModeBackend sInstance;
protected int mZenMode;
/** gets policy last set by updatePolicy **/
protected NotificationManager.Policy mPolicy;
private final NotificationManager mNotificationManager;
private String TAG = "ZenModeSettingsBackend";
private final Context mContext;
public static ZenModeBackend getInstance(Context context) {
if (sInstance == null) {
sInstance = new ZenModeBackend(context);
}
return sInstance;
}
public ZenModeBackend(Context context) {
mContext = context;
mNotificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
updateZenMode();
updatePolicy();
}
protected void updatePolicy() {
if (mNotificationManager != null) {
mPolicy = mNotificationManager.getNotificationPolicy();
}
}
protected void updateZenMode() {
mZenMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ZEN_MODE, mZenMode);
}
protected boolean setZenRule(String id, AutomaticZenRule rule) {
return NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
}
protected void setZenMode(int zenMode) {
NotificationManager.from(mContext).setZenMode(zenMode, null, TAG);
mZenMode = zenMode;
}
/** gets last zen mode set by setZenMode or updateZenMode **/
protected int getZenMode() {
mZenMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ZEN_MODE, mZenMode);
return mZenMode;
}
protected boolean isPriorityCategoryEnabled(int categoryType) {
return (mPolicy.priorityCategories & categoryType) != 0;
}
protected int getNewPriorityCategories(boolean allow, int categoryType) {
int priorityCategories = mPolicy.priorityCategories;
if (allow) {
priorityCategories |= categoryType;
} else {
priorityCategories &= ~categoryType;
}
return priorityCategories;
}
protected int getPriorityCallSenders() {
return mPolicy.priorityCallSenders;
}
protected int getPriorityMessageSenders() {
return mPolicy.priorityMessageSenders;
}
protected void saveVisualEffectsPolicy(int category, boolean canBypass) {
int suppressedEffects = getNewSuppressedEffects(!canBypass, category);
savePolicy(mPolicy.priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, suppressedEffects);
}
protected void saveSoundPolicy(int category, boolean allow) {
int priorityCategories = getNewPriorityCategories(allow, category);
savePolicy(priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, mPolicy.suppressedVisualEffects);
}
protected void savePolicy(int priorityCategories, int priorityCallSenders,
int priorityMessageSenders, int suppressedVisualEffects) {
mPolicy = new NotificationManager.Policy(priorityCategories, priorityCallSenders,
priorityMessageSenders,
suppressedVisualEffects);
mNotificationManager.setNotificationPolicy(mPolicy);
}
protected int getNewSuppressedEffects(boolean suppress, int effectType) {
int effects = mPolicy.suppressedVisualEffects;
if (suppress) {
effects |= effectType;
} else {
effects &= ~effectType;
}
return effects;
}
protected boolean isEffectAllowed(int effect) {
return (mPolicy.suppressedVisualEffects & effect) == 0;
}
protected void saveSenders(int category, int val) {
int priorityCallSenders = getPriorityCallSenders();
int priorityMessagesSenders = getPriorityMessageSenders();
int categorySenders = getPrioritySenders(category);
final boolean allowSenders = val != SOURCE_NONE;
final int allowSendersFrom = val == SOURCE_NONE ? categorySenders : val;
String stringCategory = "";
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) {
stringCategory = "Calls";
priorityCallSenders = allowSendersFrom;
}
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
stringCategory = "Messages";
priorityMessagesSenders = allowSendersFrom;
}
savePolicy(getNewPriorityCategories(allowSenders, category),
priorityCallSenders, priorityMessagesSenders, mPolicy.suppressedVisualEffects);
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allow=" +
stringCategory + allowSenders + " allow" + stringCategory + "From="
+ ZenModeConfig.sourceToString(allowSendersFrom));
}
protected String getSendersKey(int category) {
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
return getKeyFromSetting(SOURCE_NONE);
default:
int prioritySenders = getPrioritySenders(category);
return getKeyFromSetting(isPriorityCategoryEnabled(category)
? prioritySenders : SOURCE_NONE);
}
}
private int getPrioritySenders(int category) {
int categorySenders = -1;
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) {
return getPriorityCallSenders();
}
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
return getPriorityMessageSenders();
}
return categorySenders;
}
protected static String getKeyFromSetting(int contactType) {
switch (contactType) {
case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
return ZEN_MODE_FROM_ANYONE;
case NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS:
return ZEN_MODE_FROM_CONTACTS;
case NotificationManager.Policy.PRIORITY_SENDERS_STARRED:
return ZEN_MODE_FROM_STARRED;
case SOURCE_NONE:
default:
return ZEN_MODE_FROM_NONE;
}
}
protected int getContactsSummary(int category) {
int contactType = -1;
// SOURCE_NONE can be used when in total silence or alarms only
// (policy is based on user's preferences but the UI displayed is based on zenMode)
if (category == SOURCE_NONE) {
return R.string.zen_mode_from_none;
}
if (category == NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) {
if (isPriorityCategoryEnabled(category)) {
contactType = getPriorityMessageSenders();
}
} else if (category == NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) {
if (isPriorityCategoryEnabled(category)) {
contactType = getPriorityCallSenders();
}
}
switch (contactType) {
case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
return R.string.zen_mode_from_anyone;
case NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS:
return R.string.zen_mode_from_contacts;
case NotificationManager.Policy.PRIORITY_SENDERS_STARRED:
return R.string.zen_mode_from_starred;
case SOURCE_NONE:
default:
return R.string.zen_mode_from_none;
}
}
protected static int getSettingFromPrefKey(String key) {
switch (key) {
case ZEN_MODE_FROM_ANYONE:
return NotificationManager.Policy.PRIORITY_SENDERS_ANY;
case ZEN_MODE_FROM_CONTACTS:
return NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
case ZEN_MODE_FROM_STARRED:
return NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
case ZEN_MODE_FROM_NONE:
default:
return SOURCE_NONE;
}
}
public boolean removeZenRule(String ruleId) {
return NotificationManager.from(mContext).removeAutomaticZenRule(ruleId);
}
protected String addZenRule(AutomaticZenRule rule) {
try {
String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);
NotificationManager.from(mContext).getAutomaticZenRule(id);
return id;
} catch (Exception e) {
return null;
}
}
}

View File

@@ -0,0 +1,37 @@
package com.android.settings.notification;
import android.content.Context;
import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeBehaviorPreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
protected static final String KEY_BEHAVIOR_SETTINGS = "zen_mode_behavior_settings";
private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModeBehaviorPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY_BEHAVIOR_SETTINGS, lifecycle);
mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
public String getPreferenceKey() {
return KEY_BEHAVIOR_SETTINGS;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
preference.setSummary(mSummaryBuilder.getBehaviorSettingSummary(getPolicy(),
getZenMode()));
}
}

View File

@@ -16,303 +16,43 @@
package com.android.settings.notification;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class ZenModeBehaviorSettings extends ZenModeSettingsBase implements Indexable {
private static final String KEY_ALARMS = "zen_mode_alarms";
private static final String KEY_MEDIA = "zen_mode_media";
private static final String KEY_REMINDERS = "zen_mode_reminders";
private static final String KEY_EVENTS = "zen_mode_events";
private static final String KEY_MESSAGES = "zen_mode_messages";
private static final String KEY_CALLS = "zen_mode_calls";
private static final String KEY_REPEAT_CALLERS = "zen_mode_repeat_callers";
private static final String KEY_SCREEN_OFF = "zen_mode_screen_off";
private static final String KEY_SCREEN_ON = "zen_mode_screen_on";
private SwitchPreference mScreenOff;
private SwitchPreference mScreenOn;
private static final int SOURCE_NONE = -1;
private boolean mDisableListeners;
private SwitchPreference mReminders;
private SwitchPreference mEvents;
private DropDownPreference mMessages;
private DropDownPreference mCalls;
private SwitchPreference mRepeatCallers;
private SwitchPreference mAlarms;
private SwitchPreference mMediaSystemOther;
private Policy mPolicy;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.zen_mode_behavior_settings);
final PreferenceScreen root = getPreferenceScreen();
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
mReminders = (SwitchPreference) root.findPreference(KEY_REMINDERS);
mReminders.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean val = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_REMINDERS,
val);
if (DEBUG) Log.d(TAG, "onPrefChange allowReminders=" + val);
savePolicy(getNewPriorityCategories(val, Policy.PRIORITY_CATEGORY_REMINDERS),
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
mPolicy.suppressedVisualEffects);
return true;
}
});
mEvents = (SwitchPreference) root.findPreference(KEY_EVENTS);
mEvents.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean val = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_EVENTS, val);
if (DEBUG) Log.d(TAG, "onPrefChange allowEvents=" + val);
savePolicy(getNewPriorityCategories(val, Policy.PRIORITY_CATEGORY_EVENTS),
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
mPolicy.suppressedVisualEffects);
return true;
}
});
mMessages = (DropDownPreference) root.findPreference(KEY_MESSAGES);
addSources(mMessages);
mMessages.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return false;
final int val = Integer.parseInt((String) newValue);
final boolean allowMessages = val != SOURCE_NONE;
final int allowMessagesFrom =
val == SOURCE_NONE ? mPolicy.priorityMessageSenders : val;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_MESSAGES, val);
if (DEBUG) Log.d(TAG, "onPrefChange allowMessages=" + allowMessages
+ " allowMessagesFrom=" + ZenModeConfig.sourceToString(allowMessagesFrom));
savePolicy(
getNewPriorityCategories(allowMessages, Policy.PRIORITY_CATEGORY_MESSAGES),
mPolicy.priorityCallSenders, allowMessagesFrom,
mPolicy.suppressedVisualEffects);
return true;
}
});
mCalls = (DropDownPreference) root.findPreference(KEY_CALLS);
addSources(mCalls);
mCalls.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return false;
final int val = Integer.parseInt((String) newValue);
final boolean allowCalls = val != SOURCE_NONE;
final int allowCallsFrom = val == SOURCE_NONE ? mPolicy.priorityCallSenders : val;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_CALLS, val);
if (DEBUG) Log.d(TAG, "onPrefChange allowCalls=" + allowCalls
+ " allowCallsFrom=" + ZenModeConfig.sourceToString(allowCallsFrom));
savePolicy(getNewPriorityCategories(allowCalls, Policy.PRIORITY_CATEGORY_CALLS),
allowCallsFrom, mPolicy.priorityMessageSenders,
mPolicy.suppressedVisualEffects);
return true;
}
});
mRepeatCallers = (SwitchPreference) root.findPreference(KEY_REPEAT_CALLERS);
mRepeatCallers.setSummary(mContext.getString(R.string.zen_mode_repeat_callers_summary,
mContext.getResources().getInteger(com.android.internal.R.integer
.config_zen_repeat_callers_threshold)));
mRepeatCallers.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean val = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_REPEAT_CALLS,
val);
if (DEBUG) Log.d(TAG, "onPrefChange allowRepeatCallers=" + val);
int priorityCategories = getNewPriorityCategories(val,
Policy.PRIORITY_CATEGORY_REPEAT_CALLERS);
savePolicy(priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, mPolicy.suppressedVisualEffects);
return true;
}
});
mAlarms = (SwitchPreference) root.findPreference(KEY_ALARMS);
mAlarms.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean val = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_ALARMS, val);
if (DEBUG) Log.d(TAG, "onPrefChange allowAlarms=" + val);
savePolicy(getNewPriorityCategories(val, Policy.PRIORITY_CATEGORY_ALARMS),
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
mPolicy.suppressedVisualEffects);
return true;
}
});
mMediaSystemOther = (SwitchPreference) root.findPreference(KEY_MEDIA);
mMediaSystemOther.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean val = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_MEDIA, val);
if (DEBUG) Log.d(TAG, "onPrefChange allowMediaSystemOther=" + val);
savePolicy(getNewPriorityCategories(val,
Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER),
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
mPolicy.suppressedVisualEffects);
return true;
}
});
mScreenOff = (SwitchPreference) root.findPreference(KEY_SCREEN_OFF);
if (!getResources()
.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
mScreenOff.setSummary(R.string.zen_mode_screen_off_summary_no_led);
}
mScreenOff.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean bypass = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF, !bypass);
if (DEBUG) Log.d(TAG, "onPrefChange suppressWhenScreenOff=" + !bypass);
savePolicy(mPolicy.priorityCategories,
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
getNewSuppressedEffects(!bypass, Policy.SUPPRESSED_EFFECT_SCREEN_OFF));
return true;
}
});
mScreenOn = (SwitchPreference) root.findPreference(KEY_SCREEN_ON);
mScreenOn.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return true;
final boolean bypass = (Boolean) newValue;
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_ON, bypass);
if (DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOn=" + !bypass);
savePolicy(mPolicy.priorityCategories,
mPolicy.priorityCallSenders, mPolicy.priorityMessageSenders,
getNewSuppressedEffects(!bypass, Policy.SUPPRESSED_EFFECT_SCREEN_ON));
return true;
}
});
updateControls();
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeAlarmsPreferenceController(context, lifecycle));
controllers.add(new ZenModeMediaSystemOtherPreferenceController(context, lifecycle));
controllers.add(new ZenModeEventsPreferenceController(context, lifecycle));
controllers.add(new ZenModeRemindersPreferenceController(context, lifecycle));
controllers.add(new ZenModeMessagesPreferenceController(context, lifecycle));
controllers.add(new ZenModeCallsPreferenceController(context, lifecycle));
controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle));
controllers.add(new ZenModeScreenOnPreferenceController(context, lifecycle));
controllers.add(new ZenModeScreenOffPreferenceController(context, lifecycle));
return controllers;
}
@Override
protected void onZenModeChanged() {
updateControls();
}
@Override
protected void onZenModeConfigChanged() {
mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
updateControls();
}
private void updateControlsPolicy() {
if (mCalls != null) {
mCalls.setValue(Integer.toString(
isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS)
? mPolicy.priorityCallSenders : SOURCE_NONE));
}
mMessages.setValue(Integer.toString(
isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_MESSAGES)
? mPolicy.priorityMessageSenders : SOURCE_NONE));
mAlarms.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_ALARMS));
mMediaSystemOther.setChecked(isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER));
mReminders.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REMINDERS));
mEvents.setChecked(isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_EVENTS));
mRepeatCallers.setChecked(
isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS));
mRepeatCallers.setVisible(!isPriorityCategoryEnabled(Policy.PRIORITY_CATEGORY_CALLS)
|| mPolicy.priorityCallSenders != Policy.PRIORITY_SENDERS_ANY);
}
private void updateControls() {
mDisableListeners = true;
switch(mZenMode) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
toggleBasicNoInterruptions();
mAlarms.setChecked(false);
mMediaSystemOther.setChecked(false);
setTogglesEnabled(false);
break;
case Settings.Global.ZEN_MODE_ALARMS:
toggleBasicNoInterruptions();
mAlarms.setChecked(true);
mMediaSystemOther.setChecked(true);
setTogglesEnabled(false);
break;
default:
updateControlsPolicy();
setTogglesEnabled(true);
}
mScreenOff.setChecked(isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF));
mScreenOn.setChecked(isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_ON));
mDisableListeners = false;
}
private void toggleBasicNoInterruptions() {
if (mCalls != null) {
mCalls.setValue(Integer.toString(SOURCE_NONE));
}
mMessages.setValue(Integer.toString(SOURCE_NONE));
mReminders.setChecked(false);
mEvents.setChecked(false);
mRepeatCallers.setChecked(false);
}
private void setTogglesEnabled(boolean enable) {
if (mCalls != null) {
mCalls.setEnabled(enable);
}
mMessages.setEnabled(enable);
mReminders.setEnabled(enable);
mEvents.setEnabled(enable);
mRepeatCallers.setEnabled(enable);
mAlarms.setEnabled(enable);
mMediaSystemOther.setEnabled(enable);
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_behavior_settings;
}
@Override
@@ -320,67 +60,29 @@ public class ZenModeBehaviorSettings extends ZenModeSettingsBase implements Inde
return MetricsEvent.NOTIFICATION_ZEN_MODE_PRIORITY;
}
private static void addSources(DropDownPreference pref) {
pref.setEntries(new CharSequence[]{
pref.getContext().getString(R.string.zen_mode_from_anyone),
pref.getContext().getString(R.string.zen_mode_from_contacts),
pref.getContext().getString(R.string.zen_mode_from_starred),
pref.getContext().getString(R.string.zen_mode_from_none),
});
pref.setEntryValues(new CharSequence[] {
Integer.toString(Policy.PRIORITY_SENDERS_ANY),
Integer.toString(Policy.PRIORITY_SENDERS_CONTACTS),
Integer.toString(Policy.PRIORITY_SENDERS_STARRED),
Integer.toString(SOURCE_NONE),
});
}
private boolean isPriorityCategoryEnabled(int categoryType) {
return (mPolicy.priorityCategories & categoryType) != 0;
}
private int getNewPriorityCategories(boolean allow, int categoryType) {
int priorityCategories = mPolicy.priorityCategories;
if (allow) {
priorityCategories |= categoryType;
} else {
priorityCategories &= ~categoryType;
}
return priorityCategories;
}
private void savePolicy(int priorityCategories, int priorityCallSenders,
int priorityMessageSenders, int suppressedVisualEffects) {
mPolicy = new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders,
suppressedVisualEffects);
NotificationManager.from(mContext).setNotificationPolicy(mPolicy);
}
/**
* For Search.
*/
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_behavior_settings;
return Arrays.asList(sir);
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
keys.add(ZenModeAlarmsPreferenceController.KEY);
keys.add(ZenModeMediaSystemOtherPreferenceController.KEY);
keys.add(ZenModeEventsPreferenceController.KEY);
keys.add(ZenModeRemindersPreferenceController.KEY);
keys.add(ZenModeMessagesPreferenceController.KEY);
keys.add(ZenModeCallsPreferenceController.KEY);
keys.add(ZenModeRepeatCallersPreferenceController.KEY);
keys.add(ZenModeScreenOnPreferenceController.KEY);
keys.add(ZenModeScreenOffPreferenceController.KEY);
return keys;
}
};
private int getNewSuppressedEffects(boolean suppress, int effectType) {
int effects = mPolicy.suppressedVisualEffects;
if (suppress) {
effects |= effectType;
} else {
effects &= ~effectType;
}
return effects;
}
private boolean isEffectAllowed(int effect) {
return (mPolicy.suppressedVisualEffects & effect) == 0;
}
@Override
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null);
}
};
}

View File

@@ -0,0 +1,88 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.view.View;
import android.widget.Button;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
protected static final String KEY = "zen_mode_settings_button_container";
private Button mZenButtonOn;
private Button mZenButtonOff;
private ZenModeBackend mBackend;
public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
mZenButtonOn.setOnClickListener(v ->
mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS));
}
if (null == mZenButtonOff) {
mZenButtonOff = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_off_button);
mZenButtonOff.setOnClickListener(v ->
mBackend.setZenMode(Settings.Global.ZEN_MODE_OFF));
}
updateButtons();
}
private void updateButtons() {
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_ALARMS:
case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
mZenButtonOff.setVisibility(View.VISIBLE);
mZenButtonOn.setVisibility(View.GONE);
break;
case Settings.Global.ZEN_MODE_OFF:
default:
mZenButtonOff.setVisibility(View.GONE);
mZenButtonOn.setVisibility(View.VISIBLE);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeCallsPreferenceController extends
AbstractZenModePreferenceController {
protected static final String KEY = "zen_mode_calls";
private final ZenModeBackend mBackend;
public ZenModeCallsPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
preference.setEnabled(false);
preference.setSummary(mBackend.getContactsSummary(mBackend.SOURCE_NONE));
break;
default:
preference.setEnabled(true);
preference.setSummary(mBackend.getContactsSummary(
NotificationManager.Policy.PRIORITY_CATEGORY_CALLS));
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.drawable.Drawable;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.widget.RadioButtonPickerFragment;
import java.util.ArrayList;
import java.util.List;
public class ZenModeCallsSettings extends RadioButtonPickerFragment {
private ZenModeBackend mBackend;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_CALLS;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_calls_settings;
}
@Override
protected List<? extends RadioButtonPickerFragment.CandidateInfo> getCandidates() {
final String[] entries = entries();
final String[] values = keys();
final List<CallsCandidateInfo> candidates = new ArrayList<>();
if (entries == null || entries.length <= 0) return null;
if (values == null || values.length != entries.length) {
throw new IllegalArgumentException("Entries and values must be of the same length.");
}
for (int i = 0; i < entries.length; i++) {
candidates.add(new CallsCandidateInfo(entries[i], values[i]));
}
return candidates;
}
private String[] entries() {
return getResources().getStringArray(R.array.zen_mode_contacts_entries);
}
private String[] keys() {
return getResources().getStringArray(R.array.zen_mode_contacts_values);
}
@Override
protected String getDefaultKey() {
return mBackend.getSendersKey(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS);
}
@Override
protected boolean setDefaultKey(String key) {
mBackend.saveSenders(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS,
mBackend.getSettingFromPrefKey(key));
return true;
}
private static final class CallsCandidateInfo extends RadioButtonPickerFragment.CandidateInfo {
private final String name;
private final String key;
CallsCandidateInfo(String title, String value) {
super(true);
name = title;
key = value;
}
@Override
public CharSequence loadLabel() {
return name;
}
@Override
public Drawable loadIcon() {
return null;
}
@Override
public String getKey() {
return key;
}
}
}

View File

@@ -33,6 +33,7 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
import java.util.Collections;
@@ -81,6 +82,16 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
mCreate = false;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_event_rule_settings;
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
}
private void reloadCalendar() {
mCalendars = getCalendars(mContext);
ArrayList<CharSequence> entries = new ArrayList<>();
@@ -107,7 +118,6 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
@Override
protected void onCreateInternal() {
mCreate = true;
addPreferencesFromResource(R.xml.zen_mode_event_rule_settings);
final PreferenceScreen root = getPreferenceScreen();
mCalendar = (DropDownPreference) root.findPreference(KEY_CALENDAR);
@@ -243,5 +253,4 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
public String name;
public int userId;
}
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeEventsPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_events";
private final ZenModeBackend mBackend;
public ZenModeEventsPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
pref.setEnabled(false);
pref.setChecked(false);
break;
default:
pref.setChecked(mBackend.isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_EVENTS));
pref.setEnabled(true);
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowEvents = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowEvents="
+ allowEvents);
}
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_EVENTS, allowEvents);
return true;
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeMediaSystemOtherPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_media";
private final ZenModeBackend mBackend;
public ZenModeMediaSystemOtherPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
pref.setEnabled(false);
pref.setChecked(false);
break;
case Settings.Global.ZEN_MODE_ALARMS:
pref.setEnabled(false);
pref.setChecked(true);
break;
default:
pref.setEnabled(true);
pref.setChecked(mBackend.isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER));
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowMedia = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG,
"onPrefChange allowMediaSystemOther=" + allowMedia);
}
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER, allowMedia);
return true;
}
}

View File

@@ -0,0 +1,47 @@
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeMessagesPreferenceController extends
AbstractZenModePreferenceController {
protected static final String KEY = "zen_mode_messages";
private final ZenModeBackend mBackend;
public ZenModeMessagesPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
preference.setEnabled(false);
preference.setSummary(mBackend.getContactsSummary(mBackend.SOURCE_NONE));
break;
default:
preference.setEnabled(true);
preference.setSummary(mBackend.getContactsSummary(
NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
}
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.drawable.Drawable;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.widget.RadioButtonPickerFragment;
import java.util.ArrayList;
import java.util.List;
public class ZenModeMessagesSettings extends RadioButtonPickerFragment {
private ZenModeBackend mBackend;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_MESSAGES;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_messages_settings;
}
@Override
protected List<? extends RadioButtonPickerFragment.CandidateInfo> getCandidates() {
final String[] entries = entries();
final String[] values = keys();
final List<MessagesCandidateInfo> candidates = new ArrayList<>();
if (entries == null || entries.length <= 0) return null;
if (values == null || values.length != entries.length) {
throw new IllegalArgumentException("Entries and values must be of the same length.");
}
for (int i = 0; i < entries.length; i++) {
candidates.add(new MessagesCandidateInfo(entries[i], values[i]));
}
return candidates;
}
private String[] entries() {
return getResources().getStringArray(R.array.zen_mode_contacts_entries);
}
private String[] keys() {
return getResources().getStringArray(R.array.zen_mode_contacts_values);
}
@Override
protected String getDefaultKey() {
return mBackend.getSendersKey(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES);
}
@Override
protected boolean setDefaultKey(String key) {
mBackend.saveSenders(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES,
mBackend.getSettingFromPrefKey(key));
return true;
}
private final class MessagesCandidateInfo extends RadioButtonPickerFragment.CandidateInfo {
private final String name;
private final String key;
MessagesCandidateInfo(String title, String value) {
super(true);
name = title;
key = value;
}
@Override
public CharSequence loadLabel() {
return name;
}
@Override
public Drawable loadIcon() {
return null;
}
@Override
public String getKey() {
return key;
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeRemindersPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_reminders";
private final ZenModeBackend mBackend;
public ZenModeRemindersPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
pref.setEnabled(false);
pref.setChecked(false);
break;
default:
pref.setEnabled(true);
pref.setChecked(mBackend.isPriorityCategoryEnabled(
NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS));
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowReminders = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowReminders="
+ allowReminders);
mBackend.saveSoundPolicy(NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS,
allowReminders);
return true;
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.provider.Settings;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeRepeatCallersPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_repeat_callers";
private final ZenModeBackend mBackend;
public ZenModeRepeatCallersPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
switch (getZenMode()) {
case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
case Settings.Global.ZEN_MODE_ALARMS:
pref.setEnabled(false);
pref.setChecked(false);
break;
default:
boolean anyCallersCanBypassDnd = (mBackend.isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_CALLS)
&& mBackend.getPriorityCallSenders() == Policy.PRIORITY_SENDERS_ANY);
// if any caller can bypass dnd then repeat callers preference is disabled
if (anyCallersCanBypassDnd) {
pref.setEnabled(false);
pref.setChecked(true);
} else {
pref.setEnabled(true);
pref.setChecked(mBackend.isPriorityCategoryEnabled(
Policy.PRIORITY_CATEGORY_REPEAT_CALLERS));
}
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowRepeatCallers = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowRepeatCallers="
+ allowRepeatCallers);
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS, allowRepeatCallers);
return true;
}
}

View File

@@ -26,6 +26,7 @@ import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.service.notification.ConditionProviderService;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
@@ -43,8 +44,13 @@ import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.SwitchBar;
import java.util.Arrays;
import java.util.List;
public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
implements SwitchBar.OnSwitchChangeListener {
protected static final String TAG = ZenModeSettingsBase.TAG;
@@ -52,6 +58,8 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
private static final String KEY_RULE_NAME = "rule_name";
private static final String KEY_ZEN_MODE = "zen_mode";
private static final String KEY_EVENT_RULE_SETTINGS = "zen_mode_event_rule_settings";
private static final String KEY_SCHEDULE_RULE_SETTINGS = "zen_mode_schedule_rule_settings";
protected Context mContext;
protected boolean mDisableListeners;
@@ -72,8 +80,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mContext = getActivity();
final Intent intent = getActivity().getIntent();
@@ -96,6 +102,8 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
return;
}
super.onCreate(icicle);
setHasOptionsMenu(true);
onCreateInternal();
@@ -129,7 +137,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
if (zenMode == mRule.getInterruptionFilter()) return false;
if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode);
mRule.setInterruptionFilter(zenMode);
setZenRule(mId, mRule);
mBackend.setZenRule(mId, mRule);
return true;
}
});
@@ -172,7 +180,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ENABLE_RULE, enabled);
if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled);
mRule.setEnabled(enabled);
setZenRule(mId, mRule);
mBackend.setZenRule(mId, mRule);
if (enabled) {
final int toastText = getEnabledToastText();
if (toastText != 0) {
@@ -188,16 +196,12 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
protected void updateRule(Uri newConditionId) {
mRule.setConditionId(newConditionId);
setZenRule(mId, mRule);
}
@Override
protected void onZenModeChanged() {
// noop
mBackend.setZenRule(mId, mRule);
}
@Override
protected void onZenModeConfigChanged() {
super.onZenModeConfigChanged();
if (!refreshRuleOrFinish()) {
updateControls();
}
@@ -225,7 +229,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
@Override
public void onOk(String ruleName) {
mRule.setName(ruleName);
setZenRule(mId, mRule);
mBackend.setZenRule(mId, mRule);
}
}.show();
}
@@ -250,7 +254,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
mDeleting = true;
removeZenRule(mId);
mBackend.removeZenRule(mId);
}
})
.show();
@@ -294,4 +298,25 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
mDisableListeners = false;
}
/**
* For Search.
*/
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
// not indexable
return Arrays.asList(sir);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_SCHEDULE_RULE_SETTINGS);
keys.add(KEY_EVENT_RULE_SETTINGS);
return keys;
}
};
}

View File

@@ -19,7 +19,6 @@ package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.app.TimePickerDialog;
import android.content.Context;
@@ -40,10 +39,12 @@ import android.widget.TimePicker;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
private static final String KEY_DAYS = "days";
@@ -70,6 +71,16 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
return mSchedule != null;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_schedule_rule_settings;
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
}
@Override
protected String getZenModeDependency() {
return mDays.getKey();
@@ -82,7 +93,6 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
@Override
protected void onCreateInternal() {
addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings);
final PreferenceScreen root = getPreferenceScreen();
mDays = root.findPreference(KEY_DAYS);
@@ -306,5 +316,4 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
boolean onSetTime(int hour, int minute);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOffPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_screen_off";
private final ZenModeBackend mBackend;
public ZenModeScreenOffPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_OFF));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOff="
+ !bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_OFF, bypass);
return true;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOnPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceChangeListener{
protected static final String KEY = "zen_mode_screen_on";
private final ZenModeBackend mBackend;
public ZenModeScreenOnPreferenceController(Context context, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
SwitchPreference pref = (SwitchPreference) preference;
pref.setChecked(mBackend.isEffectAllowed(Policy.SUPPRESSED_EFFECT_SCREEN_ON));
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOn="
+ !bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_ON, bypass);
return true;
}
}

View File

@@ -20,56 +20,28 @@ import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
private static final String KEY_BEHAVIOR_SETTINGS = "zen_mode_behavior_settings";
private static final String KEY_AUTOMATION_SETTINGS = "zen_mode_automation_settings";
private Preference mBehaviorSettings;
private Preference mAutomationSettings;
private Policy mPolicy;
private SummaryBuilder mSummaryBuilder;
public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.zen_mode_settings);
final PreferenceScreen root = getPreferenceScreen();
mBehaviorSettings = root.findPreference(KEY_BEHAVIOR_SETTINGS);
mAutomationSettings = root.findPreference(KEY_AUTOMATION_SETTINGS);
mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
mSummaryBuilder = new SummaryBuilder(getContext());
}
@Override
public void onResume() {
super.onResume();
if (isUiRestricted()) {
return;
}
updateControls();
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_settings;
}
@Override
@@ -78,27 +50,8 @@ public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
}
@Override
protected void onZenModeChanged() {
updateControls();
}
@Override
protected void onZenModeConfigChanged() {
mPolicy = NotificationManager.from(mContext).getNotificationPolicy();
updateControls();
}
private void updateControls() {
updateBehaviorSettingsSummary();
updateAutomationSettingsSummary();
}
private void updateBehaviorSettingsSummary() {
mBehaviorSettings.setSummary(mSummaryBuilder.getBehaviorSettingSummary(mPolicy, mZenMode));
}
private void updateAutomationSettingsSummary() {
mAutomationSettings.setSummary(mSummaryBuilder.getAutomaticRulesSummary());
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
@Override
@@ -106,6 +59,16 @@ public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
return R.string.help_uri_interruptions;
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle));
return controllers;
}
public static class SummaryBuilder {
private Context mContext;
@@ -227,42 +190,29 @@ public class ZenModeSettings extends ZenModeSettingsBase implements Indexable {
}
}
private static final Comparator<Entry<String,AutomaticZenRule>> RULE_COMPARATOR =
new Comparator<Map.Entry<String,AutomaticZenRule>>() {
@Override
public int compare(Map.Entry<String,AutomaticZenRule> lhs,
Map.Entry<String,AutomaticZenRule> rhs) {
int byDate = Long.compare(lhs.getValue().getCreationTime(),
rhs.getValue().getCreationTime());
if (byDate != 0) {
return byDate;
} else {
return key(lhs.getValue()).compareTo(key(rhs.getValue()));
}
}
private String key(AutomaticZenRule rule) {
final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId())
? 1
: ZenModeConfig.isValidEventConditionId(rule.getConditionId())
? 2
: 3;
return type + rule.getName().toString();
}
};
/**
* For Search.
*/
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_settings;
return Arrays.asList(sir);
}
};
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_settings;
return Arrays.asList(sir);
}
@Override
public List<String> getNonIndexableKeys(Context context) {
List<String> keys = super.getNonIndexableKeys(context);
keys.add(ZenModeButtonPreferenceController.KEY);
return keys;
}
@Override
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null);
}
};
}

View File

@@ -16,8 +16,6 @@
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
@@ -26,17 +24,11 @@ import android.os.Handler;
import android.os.UserManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.util.Log;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment {
abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
protected static final String TAG = "ZenModeSettings";
protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -44,30 +36,33 @@ abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment {
private final SettingsObserver mSettingsObserver = new SettingsObserver();
protected Context mContext;
protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
protected int mZenMode;
abstract protected void onZenModeChanged();
abstract protected void onZenModeConfigChanged();
protected ZenModeBackend mBackend;
protected void onZenModeConfigChanged() {};
public ZenModeSettingsBase() {
super(UserManager.DISALLOW_ADJUST_VOLUME);
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mContext = getActivity();
mBackend = ZenModeBackend.getInstance(mContext);
super.onCreate(icicle);
updateZenMode(false /*fireChanged*/);
maybeRefreshRules(true, false /*fireChanged*/);
if (DEBUG) Log.d(TAG, "Loaded mRules=" + mRules);
}
@Override
public void onResume() {
super.onResume();
updateZenMode(true /*fireChanged*/);
maybeRefreshRules(true, true /*fireChanged*/);
mSettingsObserver.register();
if (isUiRestricted()) {
if (isUiRestrictedByOnlyAdmin()) {
@@ -89,56 +84,7 @@ abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment {
final int zenMode = Settings.Global.getInt(getContentResolver(), Global.ZEN_MODE, mZenMode);
if (zenMode == mZenMode) return;
mZenMode = zenMode;
if (DEBUG) Log.d(TAG, "updateZenMode mZenMode=" + mZenMode);
if (fireChanged) {
onZenModeChanged();
}
}
protected String addZenRule(AutomaticZenRule rule) {
try {
String id = NotificationManager.from(mContext).addAutomaticZenRule(rule);
final AutomaticZenRule savedRule =
NotificationManager.from(mContext).getAutomaticZenRule(id);
maybeRefreshRules(savedRule != null, true);
return id;
} catch (Exception e) {
return null;
}
}
protected boolean setZenRule(String id, AutomaticZenRule rule) {
final boolean success =
NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
maybeRefreshRules(success, true);
return success;
}
protected boolean removeZenRule(String id) {
final boolean success =
NotificationManager.from(mContext).removeAutomaticZenRule(id);
maybeRefreshRules(success, true);
return success;
}
protected void maybeRefreshRules(boolean success, boolean fireChanged) {
if (success) {
mRules = getZenModeRules();
if (DEBUG) Log.d(TAG, "Refreshed mRules=" + mRules);
if (fireChanged) {
onZenModeConfigChanged();
}
}
}
protected void setZenMode(int zenMode, Uri conditionId) {
NotificationManager.from(mContext).setZenMode(zenMode, conditionId, TAG);
}
private Set<Map.Entry<String, AutomaticZenRule>> getZenModeRules() {
Map<String, AutomaticZenRule> ruleMap
= NotificationManager.from(mContext).getAutomaticZenRules();
return ruleMap.entrySet();
if (DEBUG) Log.d(TAG, "updateZenMode mZenMode=" + mZenMode + " " + fireChanged);
}
private final class SettingsObserver extends ContentObserver {
@@ -165,7 +111,8 @@ abstract public class ZenModeSettingsBase extends RestrictedSettingsFragment {
updateZenMode(true /*fireChanged*/);
}
if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
maybeRefreshRules(true, true /*fireChanged*/);
mBackend.updatePolicy();
onZenModeConfigChanged();
}
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.service.notification.ZenModeConfig;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceViewHolder;
import android.view.View;
import com.android.settings.R;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
import com.android.settingslib.TwoTargetPreference;
import java.util.Map;
public class ZenRulePreference extends TwoTargetPreference {
protected final ManagedServiceSettings.Config CONFIG =
ZenModeAutomationSettings.getConditionProviderConfig();
final CharSequence mName;
final String mId;
boolean appExists;
final PreferenceCategory mParent;
final Preference mPref;
final Context mContext;
final ZenModeBackend mBackend;
final ZenServiceListing mServiceListing;
final PackageManager mPm;
public ZenRulePreference(Context context,
final Map.Entry<String, AutomaticZenRule> ruleEntry,
PreferenceCategory prefCategory) {
super(context);
mBackend = ZenModeBackend.getInstance(context);
mContext = context;
final AutomaticZenRule rule = ruleEntry.getValue();
mName = rule.getName();
mId = ruleEntry.getKey();
mParent = prefCategory;
mPm = mContext.getPackageManager();
mServiceListing = new ZenServiceListing(mContext, CONFIG);
mServiceListing.reloadApprovedServices();
mPref = this;
setAttributes(rule);
}
@Override
protected int getSecondTargetResId() {
return R.layout.zen_rule_widget;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
View v = view.findViewById(R.id.delete_zen_rule);
if (v != null) {
v.setOnClickListener(mDeleteListener);
}
}
private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
showDeleteRuleDialog(mId, mName, mParent, mPref);
}
};
private void showDeleteRuleDialog(final String ruleId, final CharSequence ruleName,
PreferenceCategory parent, Preference pref) {
new AlertDialog.Builder(mContext)
.setMessage(mContext.getResources().getString(
R.string.zen_mode_delete_rule_confirmation, ruleName))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_delete_rule_button,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mBackend.removeZenRule(ruleId);
parent.removePreference(pref);
}
})
.show();
}
protected void setAttributes(AutomaticZenRule rule) {
final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
rule.getConditionId());
final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
final boolean isSystemRule = isSchedule || isEvent;
try {
ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
} catch (PackageManager.NameNotFoundException e) {
appExists = false;
return;
}
appExists = true;
setTitle(rule.getName());
setPersistent(false);
final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
: isEvent ? ZenModeEventRuleSettings.ACTION : "";
ServiceInfo si = mServiceListing.findService(rule.getOwner());
ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
getSettingsActivity(si);
setIntent(AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
settingsActivity, mId));
setSelectable(settingsActivity != null || isSystemRule);
setKey(mId);
}
private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
CharSequence providerLabel) {
final String mode = computeZenModeCaption(mContext.getResources(),
rule.getInterruptionFilter());
final String ruleState = (rule == null || !rule.isEnabled())
? mContext.getResources().getString(R.string.switch_off_text)
: mContext.getResources().getString(
R.string.zen_mode_rule_summary_enabled_combination, mode);
return ruleState;
}
private static String computeZenModeCaption(Resources res, int zenMode) {
switch (zenMode) {
case NotificationManager.INTERRUPTION_FILTER_ALARMS:
return res.getString(R.string.zen_mode_option_alarms);
case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
return res.getString(R.string.zen_mode_option_important_interruptions);
case NotificationManager.INTERRUPTION_FILTER_NONE:
return res.getString(R.string.zen_mode_option_no_interruptions);
default:
return null;
}
}
}

View File

@@ -164,7 +164,8 @@ public abstract class ZenRuleSelectionDialog {
if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
Set<ZenRuleInfo> externalRuleTypes = new TreeSet<>(RULE_TYPE_COMPARATOR);
for (ServiceInfo serviceInfo : services) {
final ZenRuleInfo ri = ZenModeAutomationSettings.getRuleInfo(mPm, serviceInfo);
final ZenRuleInfo ri = AbstractZenModeAutomaticRulePreferenceController.
getRuleInfo(mPm, serviceInfo);
if (ri != null && ri.configurationActivity != null
&& mNm.isNotificationPolicyAccessGrantedForPackage(ri.packageName)
&& (ri.ruleInstanceLimit <= 0 || ri.ruleInstanceLimit

View File

@@ -69,6 +69,8 @@ import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
import com.android.settings.notification.ZenModeBehaviorSettings;
import com.android.settings.notification.ZenModeEventRuleSettings;
import com.android.settings.notification.ZenModeScheduleRuleSettings;
import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.security.EncryptionAndCredential;
@@ -168,6 +170,8 @@ public final class SearchIndexableResources {
addIndex(LockscreenDashboardFragment.class);
addIndex(ZenModeBehaviorSettings.class);
addIndex(ZenModeAutomationSettings.class);
addIndex(ZenModeEventRuleSettings.class);
addIndex(ZenModeScheduleRuleSettings.class);
}
private SearchIndexableResources() {