Snap for 4489599 from e677f49328 to pi-release

Change-Id: Iafc4a1036c6b050b2a6424fa3effb73ececbc6e3
This commit is contained in:
android-build-team Robot
2017-12-07 08:29:29 +00:00
32 changed files with 1081 additions and 443 deletions

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 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.
-->
<!-- Based off frameworks/base/core/res/res/layout/preference_dropdown_material.xml
except that icon space in this layout is always reserved -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Spinner
android:id="@+id/spinner"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/preference_no_icon_padding_start"
android:visibility="invisible" />
<include layout="@layout/preference_material"/>
</FrameLayout>

View File

@@ -6741,6 +6741,9 @@
<!-- Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
<string name="zen_mode_automation_settings_page_title">Automatic rules</string>
<!-- Do not disturb: Title for a specific zen mode automatic rule in settings. [CHAR LIMIT=30] -->
<string name="zen_mode_automatic_rule_settings_page_title">Automatic rule</string>
<!-- Do not disturb: Title for the zen mode automation option Suggestion. [CHAR LIMIT=50] -->
<string name="zen_mode_automation_suggestion_title">Set Do Not Disturb rules</string>

View File

@@ -20,19 +20,19 @@
<resources>
<!-- Fragment style -->
<style name="SettingsPreferenceFragmentStyle" parent="@style/PreferenceFragment.Material">
<style name="SettingsPreferenceFragmentStyle" parent="@style/PreferenceFragmentStyle.SettingsBase">
<item name="android:layout">@layout/preference_list_fragment</item>
</style>
<style name="ApnPreference" parent="@style/Preference.Material">
<style name="ApnPreference" parent="Preference.SettingsBase">
<item name="android:layout">@layout/apn_preference_layout</item>
</style>
<style name="SettingsSeekBarPreference" parent="@style/Preference.Material">
<style name="SettingsSeekBarPreference" parent="Preference.SettingsBase">
<item name="android:layout">@layout/preference_widget_seekbar_settings</item>
</style>
<style name="SyncSwitchPreference" parent="@style/Preference.Material">
<style name="SyncSwitchPreference" parent="Preference.SettingsBase">
<item name="android:widgetLayout">@layout/preference_widget_sync_toggle</item>
</style>

View File

@@ -15,8 +15,18 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_event_rule_settings" >
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_event_rule_settings"
android:title="@string/zen_mode_automatic_rule_settings_page_title">
<com.android.settings.applications.LayoutPreference
android:key="pref_app_header"
android:layout="@layout/settings_entity_header" />
<com.android.settings.applications.LayoutPreference
android:key="zen_automatic_rule_switch"
android:layout="@layout/styled_switch_bar" />
<!-- Rule name -->
<Preference
@@ -36,10 +46,4 @@
android:title="@string/zen_mode_event_rule_reply"
android:summary="%s" />
<!-- Zen mode -->
<DropDownPreference
android:key="zen_mode"
android:title="@string/zen_mode_settings_title"
android:summary="%s" />
</PreferenceScreen>

View File

@@ -15,8 +15,18 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_schedule_rule_settings" >
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_schedule_rule_settings"
android:title="@string/zen_mode_automatic_rule_settings_page_title">
<com.android.settings.applications.LayoutPreference
android:key="pref_app_header"
android:layout="@layout/settings_entity_header" />
<com.android.settings.applications.LayoutPreference
android:key="zen_automatic_rule_switch"
android:layout="@layout/styled_switch_bar" />
<!-- Rule name -->
<Preference
@@ -39,11 +49,4 @@
android:summary="@string/zen_mode_schedule_alarm_summary"
android:order="99" />
<!-- Zen mode -->
<DropDownPreference
android:key="zen_mode"
android:title="@string/zen_mode_settings_title"
android:order="100"
android:summary="%s" />
</PreferenceScreen>

View File

@@ -83,15 +83,22 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Bundle arguments = getArguments();
if (FeatureFlagUtils.isEnabled(getContext(), DEVICE_INFO_V2) || true) {
// Increase the number of children when the device contains more than 1 sim.
final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(
Context.TELEPHONY_SERVICE);
final int numberOfChildren = Math.max(SIM_PREFERENCES_COUNT,
SIM_PREFERENCES_COUNT * telephonyManager.getPhoneCount())
+ NON_SIM_PREFERENCES_COUNT;
getPreferenceScreen().setInitialExpandedChildrenCount(numberOfChildren);
// Do not override initial expand children count if we come from
// search (EXTRA_FRAGMENT_ARG_KEY is set) - we need to display every if entry point
// is search.
if (arguments == null
|| !arguments.containsKey(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY)) {
// Increase the number of children when the device contains more than 1 sim.
final TelephonyManager telephonyManager = (TelephonyManager) getSystemService(
Context.TELEPHONY_SERVICE);
final int numberOfChildren = Math.max(SIM_PREFERENCES_COUNT,
SIM_PREFERENCES_COUNT * telephonyManager.getPhoneCount())
+ NON_SIM_PREFERENCES_COUNT;
getPreferenceScreen().setInitialExpandedChildrenCount(numberOfChildren);
}
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.accessibility;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -27,6 +28,7 @@ import android.support.v7.preference.Preference;
import android.view.accessibility.AccessibilityManager;
import android.widget.Switch;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -87,7 +89,7 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
super.onInstallSwitchBarToggleSwitch();
mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> {
Context context = getContext();
if (enabled && (getServiceInfo(context) == null)) {
if (enabled && !shortcutFeatureAvailable(context)) {
// If no service is configured, we'll disable the shortcut shortly. Give the
// user a chance to select a service. We'll update the preferences when we resume.
Settings.Secure.putInt(
@@ -110,7 +112,7 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
ContentResolver cr = getContentResolver();
Context context = getContext();
mServicePreference.setSummary(getServiceName(context));
if (getServiceInfo(context) == null) {
if (!shortcutFeatureAvailable(context)) {
// If no service is configured, make sure the overall shortcut is turned off
Settings.Secure.putInt(
getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0);
@@ -132,19 +134,38 @@ public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePrefer
* @return The name of the service or a string saying that none is selected.
*/
public static CharSequence getServiceName(Context context) {
if (!shortcutFeatureAvailable(context)) {
return context.getString(R.string.accessibility_no_service_selected);
}
AccessibilityServiceInfo shortcutServiceInfo = getServiceInfo(context);
if (shortcutServiceInfo != null) {
return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager());
}
return context.getString(R.string.accessibility_no_service_selected);
return AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
.get(getShortcutComponent(context)).getLabel(context);
}
private static AccessibilityServiceInfo getServiceInfo(Context context) {
ComponentName shortcutServiceName = ComponentName.unflattenFromString(
AccessibilityUtils.getShortcutTargetServiceComponentNameString(
context, UserHandle.myUserId()));
return AccessibilityManager.getInstance(context)
.getInstalledServiceInfoWithComponentName(shortcutServiceName);
.getInstalledServiceInfoWithComponentName(getShortcutComponent(context));
}
private static boolean shortcutFeatureAvailable(Context context) {
ComponentName shortcutFeature = getShortcutComponent(context);
if (shortcutFeature == null) return false;
if (AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
.containsKey(shortcutFeature)) {
return true;
}
return getServiceInfo(context) != null;
}
private static @Nullable ComponentName getShortcutComponent(Context context) {
String componentNameString = AccessibilityUtils.getShortcutTargetServiceComponentNameString(
context, UserHandle.myUserId());
if (componentNameString == null) return null;
return ComponentName.unflattenFromString(componentNameString);
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =

View File

@@ -25,29 +25,40 @@ import android.app.Fragment;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ApplicationInfo;
import android.content.pm.ComponentInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.IconDrawableFactory;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.accessibility.AccessibilityShortcutController.ToggleableFrameworkFeatureInfo;
import com.android.settings.R;
import com.android.settings.applications.defaultapps.DefaultAppInfo;
import com.android.settings.applications.defaultapps.DefaultAppPickerFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settings.wrapper.IPackageManagerWrapper;
import com.android.settingslib.accessibility.AccessibilityUtils;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Fragment for picking accessibility shortcut service
*/
public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
public class ShortcutServicePickerFragment extends RadioButtonPickerFragment {
@Override
public int getMetricsCategory() {
@@ -60,22 +71,29 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
}
@Override
protected List<? extends DefaultAppInfo> getCandidates() {
protected List<? extends CandidateInfo> getCandidates() {
final Context context = getContext();
final PackageManager pm = context.getPackageManager();
final AccessibilityManager accessibilityManager = context
.getSystemService(AccessibilityManager.class);
final List<AccessibilityServiceInfo> installedServices =
accessibilityManager.getInstalledAccessibilityServiceList();
final int numInstalledServices = installedServices.size();
final PackageManagerWrapper pmw = new PackageManagerWrapper(context.getPackageManager());
List<DefaultAppInfo> candidates = new ArrayList<>(numInstalledServices);
final List<CandidateInfo> candidates = new ArrayList<>(numInstalledServices);
Map<ComponentName, ToggleableFrameworkFeatureInfo> frameworkFeatureInfoMap =
AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
for (ComponentName componentName : frameworkFeatureInfoMap.keySet()) {
// Lookup icon
candidates.add(new FrameworkCandidateInfo(frameworkFeatureInfoMap.get(componentName),
R.drawable.empty_icon, componentName.flattenToString()));
}
for (int i = 0; i < numInstalledServices; i++) {
AccessibilityServiceInfo installedServiceInfo = installedServices.get(i);
candidates.add(new DefaultAppInfo(context, mPm,
UserHandle.myUserId(),
final AccessibilityServiceInfo installedServiceInfo = installedServices.get(i);
candidates.add(new DefaultAppInfo(context, pmw, UserHandle.myUserId(),
installedServiceInfo.getComponentName(),
(String) installedServiceInfo.loadSummary(mPm.getPackageManager()),
true /* enabled */));
(String) installedServiceInfo.loadSummary(pm), true /* enabled */));
}
return candidates;
@@ -105,13 +123,21 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
public void onRadioButtonClicked(RadioButtonPreference selected) {
final String selectedKey = selected.getKey();
final Activity activity = getActivity();
if (TextUtils.isEmpty(selectedKey)) {
super.onRadioButtonClicked(selected);
} else if (activity != null) {
final DialogFragment fragment = ConfirmationDialogFragment.newInstance(
this, selectedKey);
fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG);
} else {
final ComponentName selectedComponent = ComponentName.unflattenFromString(selectedKey);
if (AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
.containsKey(selectedComponent)) {
// This is a framework feature. It doesn't need to be confirmed.
onRadioButtonConfirmed(selectedKey);
} else {
final Activity activity = getActivity();
if (activity != null) {
ConfirmationDialogFragment.newInstance(this, selectedKey)
.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG);
}
}
}
}
@@ -156,11 +182,40 @@ public class ShortcutServicePickerFragment extends DefaultAppPickerFragment {
@Override
public void onClick(DialogInterface dialog, int which) {
final Fragment fragment = getTargetFragment();
if ((which == BUTTON_POSITIVE) && (fragment instanceof DefaultAppPickerFragment)) {
if ((which == BUTTON_POSITIVE) && (fragment instanceof ShortcutServicePickerFragment)) {
final Bundle bundle = getArguments();
((ShortcutServicePickerFragment) fragment).onServiceConfirmed(
bundle.getString(EXTRA_KEY));
}
}
}
private class FrameworkCandidateInfo extends CandidateInfo {
ToggleableFrameworkFeatureInfo mToggleableFrameworkFeatureInfo;
int mIconResId;
String mKey;
public FrameworkCandidateInfo(
ToggleableFrameworkFeatureInfo frameworkFeatureInfo, int iconResId, String key) {
super(true /* enabled */);
mToggleableFrameworkFeatureInfo = frameworkFeatureInfo;
mIconResId = iconResId;
mKey = key;
}
@Override
public CharSequence loadLabel() {
return mToggleableFrameworkFeatureInfo.getLabel(getContext());
}
@Override
public Drawable loadIcon() {
return getContext().getDrawable(mIconResId);
}
@Override
public String getKey() {
return mKey;
}
}
}

View File

@@ -16,18 +16,26 @@
package com.android.settings.deviceinfo;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.app.ActivityManager;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import android.util.DebugUtils;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.RadioButton;
import com.android.settings.R;
import java.io.File;
public class StorageWizardInit extends StorageWizardBase {
private RadioButton mRadioExternal;
private RadioButton mRadioInternal;
@@ -69,12 +77,15 @@ public class StorageWizardInit extends StorageWizardBase {
mRadioExternal.setChecked(true);
onNavigateNext();
finish();
}
// TODO: Show a message about why this is disabled for guest and that only an admin user
// can adopt an sd card.
if (!mIsPermittedToAdopt) {
} else if (!mIsPermittedToAdopt) {
// TODO: Show a message about why this is disabled for guest and
// that only an admin user can adopt an sd card.
mRadioInternal.setEnabled(false);
} else if (mVolume != null && mVolume.getType() == VolumeInfo.TYPE_PUBLIC
&& mVolume.isMountedReadable()) {
// Device is mounted, so classify contents to possibly pick a
// recommended default operation.
new ClassifyTask().execute(mVolume.getPath());
}
}
@@ -121,4 +132,29 @@ public class StorageWizardInit extends StorageWizardBase {
startActivity(intent);
}
}
/**
* Task that classifies the contents of a mounted storage device, and sets a
* recommended default operation based on result.
*/
public class ClassifyTask extends AsyncTask<File, Void, Integer> {
@Override
protected Integer doInBackground(File... params) {
int classes = Environment.classifyExternalStorageDirectory(params[0]);
Log.v(TAG, "Classified " + params[0] + " as "
+ DebugUtils.flagsToString(Environment.class, "HAS_", classes));
return classes;
}
@Override
protected void onPostExecute(Integer classes) {
if (classes == 0) {
// Empty is strong signal for adopt
mRadioInternal.setChecked(true);
} else if ((classes & (Environment.HAS_PICTURES | Environment.HAS_DCIM)) != 0) {
// Photos is strong signal for portable
mRadioExternal.setChecked(true);
}
}
}
}

View File

@@ -29,28 +29,31 @@ import android.service.notification.ConditionProviderService;
import android.service.notification.ZenModeConfig;
import android.support.v7.preference.Preference;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
abstract public class AbstractZenModeAutomaticRulePreferenceController extends
AbstractPreferenceController implements PreferenceControllerMixin {
AbstractZenModePreferenceController implements PreferenceControllerMixin {
private static final String TAG = "ZenModeAutomaticRule";
protected ZenModeBackend mBackend;
protected Fragment mParent;
protected Set<Map.Entry<String, AutomaticZenRule>> mRules;
protected PackageManager mPm;
private static List<String> mDefaultRuleIds;
public AbstractZenModeAutomaticRulePreferenceController(Context context, Fragment parent) {
super(context);
public AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment
parent, Lifecycle lifecycle) {
super(context, key, lifecycle);
mBackend = ZenModeBackend.getInstance(context);
mParent = parent;
mPm = mContext.getPackageManager();
mParent = parent;
}
@Override
@@ -59,25 +62,22 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
mRules = getZenModeRules();
}
private static List<String> getDefaultRuleIds() {
if (mDefaultRuleIds == null) {
mDefaultRuleIds = ZenModeConfig.DEFAULT_RULE_IDS;
}
return mDefaultRuleIds;
}
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 void showNameRuleDialog(final ZenRuleInfo ri, Fragment parent) {
ZenRuleNameDialog.show(parent, null, ri.defaultConditionId, new
RuleNameChangeListener(ri));
}
protected Map.Entry<String, AutomaticZenRule>[] sortedRules() {
@@ -108,6 +108,13 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
@Override
public int compare(Map.Entry<String, AutomaticZenRule> lhs,
Map.Entry<String, AutomaticZenRule> rhs) {
// if it's a default rule, should be at the top of automatic rules
boolean lhsIsDefaultRule = getDefaultRuleIds().contains(lhs.getKey());
boolean rhsIsDefaultRule = getDefaultRuleIds().contains(rhs.getKey());
if (lhsIsDefaultRule != rhsIsDefaultRule) {
return lhsIsDefaultRule ? -1 : 1;
}
int byDate = Long.compare(lhs.getValue().getCreationTime(),
rhs.getValue().getCreationTime());
if (byDate != 0) {
@@ -157,4 +164,26 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
}
return null;
}
public class RuleNameChangeListener implements ZenRuleNameDialog.PositiveClickListener {
ZenRuleInfo mRuleInfo;
public RuleNameChangeListener(ZenRuleInfo ruleInfo) {
mRuleInfo = ruleInfo;
}
@Override
public void onOk(String ruleName, Fragment parent) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent,
mRuleInfo.defaultConditionId,
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
String savedRuleId = mBackend.addZenRule(rule);
if (savedRuleId != null) {
parent.startActivity(getRuleIntent(mRuleInfo.settingsAction, null,
savedRuleId));
}
}
}
}

View File

@@ -35,6 +35,8 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -51,6 +53,7 @@ abstract public class AbstractZenModePreferenceController extends
private final String KEY;
final private NotificationManager mNotificationManager;
protected static ZenModeConfigWrapper mZenModeConfigWrapper;
protected MetricsFeatureProvider mMetricsFeatureProvider;
public AbstractZenModePreferenceController(Context context, String key,
Lifecycle lifecycle) {
@@ -62,6 +65,9 @@ abstract public class AbstractZenModePreferenceController extends
KEY = key;
mNotificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
}
@Override

View File

@@ -0,0 +1,104 @@
/*
* 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 static com.android.settings.widget.EntityHeaderController.PREF_KEY_APP_HEADER;
import android.app.AutomaticZenRule;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.support.v14.preference.PreferenceFragment;
import android.support.v7.preference.Preference;
import android.util.Slog;
import android.view.View;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.EntityHeaderController;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
private final String KEY = PREF_KEY_APP_HEADER;
private final PreferenceFragment mFragment;
private AutomaticZenRule mRule;
private EntityHeaderController mController;
public ZenAutomaticRuleHeaderPreferenceController(Context context, PreferenceFragment fragment,
Lifecycle lifecycle) {
super(context, PREF_KEY_APP_HEADER, lifecycle);
mFragment = fragment;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return mRule != null;
}
public void updateState(Preference preference) {
if (mRule == null) {
return;
}
if (mFragment != null) {
LayoutPreference pref = (LayoutPreference) preference;
if (mController == null) {
mController = EntityHeaderController
.newInstance(mFragment.getActivity(), mFragment,
pref.findViewById(R.id.entity_header));
}
pref = mController.setIcon(getIcon())
.setLabel(mRule.getName())
.setPackageName(mRule.getOwner().getPackageName())
.setUid(mContext.getUserId())
.setHasAppInfoLink(false)
.setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
EntityHeaderController.ActionType.ACTION_NONE)
.done(mFragment.getActivity(), mContext);
pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE);
}
}
private Drawable getIcon() {
try {
PackageManager packageManager = mContext.getPackageManager();
ApplicationInfo info = packageManager.getApplicationInfo(
mRule.getOwner().getPackageName(), 0);
return info.loadIcon(packageManager);
} catch (PackageManager.NameNotFoundException e) {
Slog.w(TAG, "Unable to load icon - PackageManager.NameNotFoundException");
}
return null;
}
protected void onResume(AutomaticZenRule rule) {
mRule = rule;
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.widget.Switch;
import android.widget.Toast;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenAutomaticRuleSwitchPreferenceController extends
AbstractZenModeAutomaticRulePreferenceController implements
SwitchBar.OnSwitchChangeListener {
private static final String KEY = "zen_automatic_rule_switch";
private AutomaticZenRule mRule;
private String mId;
private Toast mEnabledToast;
private int mToastTextResource;
public ZenAutomaticRuleSwitchPreferenceController(Context context, Fragment parent,
int toastTextResource, Lifecycle lifecycle) {
super(context, KEY, parent, lifecycle);
mToastTextResource = toastTextResource;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return mRule != null && mId != null;
}
public void onResume(AutomaticZenRule rule, String id) {
mRule = rule;
mId = id;
}
public void updateState(Preference preference) {
LayoutPreference pref = (LayoutPreference) preference;
SwitchBar bar = pref.findViewById(R.id.switch_bar);
if (mRule != null) {
bar.setChecked(mRule.isEnabled());
}
if (bar != null) {
bar.show();
try {
bar.addOnSwitchChangeListener(this);
} catch (IllegalStateException e) {
// an exception is thrown if you try to add the listener twice
}
}
bar.show();
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
final boolean enabled = isChecked;
if (enabled == mRule.isEnabled()) return;
mRule.setEnabled(enabled);
mBackend.setZenRule(mId, mRule);
if (enabled) {
final int toastText = mToastTextResource;
if (toastText != 0) {
mEnabledToast = Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT);
mEnabledToast.show();
}
} else {
if (mEnabledToast != null) {
mEnabledToast.cancel();
}
}
}
}

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.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class ZenDeleteRuleDialog extends InstrumentedDialogFragment {
protected static final String TAG = "ZenDeleteRuleDialog";
private static final String EXTRA_ZEN_RULE_NAME = "zen_rule_name";
private static final String EXTRA_ZEN_RULE_ID = "zen_rule_id";
protected static PositiveClickListener mPositiveClickListener;
/**
* The interface we expect a listener to implement.
*/
public interface PositiveClickListener {
void onOk(String id);
}
public static void show(Fragment parent, String ruleName, String id, PositiveClickListener
listener) {
final Bundle args = new Bundle();
args.putString(EXTRA_ZEN_RULE_NAME, ruleName);
args.putString(EXTRA_ZEN_RULE_ID, id);
mPositiveClickListener = listener;
ZenDeleteRuleDialog dialog = new ZenDeleteRuleDialog();
dialog.setArguments(args);
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(), TAG);
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_DELETE_RULE_DIALOG;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
String ruleName = arguments.getString(EXTRA_ZEN_RULE_NAME);
String id = arguments.getString(EXTRA_ZEN_RULE_ID);
final AlertDialog dialog = new AlertDialog.Builder(getContext())
.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) {
if (arguments != null) {
mPositiveClickListener.onOk(id);
}
}
}).create();
final View messageView = dialog.findViewById(android.R.id.message);
if (messageView != null) {
messageView.setTextDirection(View.TEXT_DIRECTION_LOCALE);
}
return dialog;
}
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settings.utils.ZenServiceListing;
@@ -28,19 +29,18 @@ public class ZenModeAddAutomaticRulePreferenceController extends
AbstractZenModeAutomaticRulePreferenceController implements
Preference.OnPreferenceClickListener {
private final String KEY_ADD_RULE;
protected static final String KEY = "zen_mode_add_automatic_rule";
private final ZenServiceListing mZenServiceListing;
public ZenModeAddAutomaticRulePreferenceController(Context context, String key,
Fragment parent, ZenServiceListing serviceListing) {
super(context, parent);
KEY_ADD_RULE = key;
public ZenModeAddAutomaticRulePreferenceController(Context context, Fragment parent,
ZenServiceListing serviceListing, Lifecycle lifecycle) {
super(context, KEY, parent, lifecycle);
mZenServiceListing = serviceListing;
}
@Override
public String getPreferenceKey() {
return KEY_ADD_RULE;
return KEY;
}
@Override
@@ -51,25 +51,30 @@ public class ZenModeAddAutomaticRulePreferenceController extends
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
Preference pref = screen.findPreference(KEY_ADD_RULE);
Preference pref = screen.findPreference(KEY);
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();
ZenRuleSelectionDialog.show(mContext, mParent, new RuleSelectionListener(),
mZenServiceListing);
return true;
}
public class RuleSelectionListener implements ZenRuleSelectionDialog.PositiveClickListener {
public RuleSelectionListener() {}
@Override
public void onSystemRuleSelected(ZenRuleInfo ri, Fragment parent) {
showNameRuleDialog(ri, parent);
}
@Override
public void onExternalRuleSelected(ZenRuleInfo ri, Fragment parent) {
Intent intent = new Intent().setComponent(ri.configurationActivity);
parent.startActivity(intent);
}
}
}

View File

@@ -23,6 +23,7 @@ import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeAlarmsPreferenceController extends
@@ -73,6 +74,9 @@ public class ZenModeAlarmsPreferenceController extends
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowAlarms=" + allowAlarms);
}
mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_ALARMS,
allowAlarms);
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_ALARMS, allowAlarms);
return true;
}

View File

@@ -19,28 +19,31 @@ package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.app.Fragment;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Map;
public class ZenModeAutomaticRulesPreferenceController extends
AbstractZenModeAutomaticRulePreferenceController {
private final String KEY_AUTOMATIC_RULES;
private PreferenceCategory mPreferenceCategory;
Map.Entry<String, AutomaticZenRule>[] mSortedRules;
protected static final String KEY = "zen_mode_automatic_rules";
public ZenModeAutomaticRulesPreferenceController(Context context, String key,
Fragment parent) {
super(context, parent);
KEY_AUTOMATIC_RULES = key;
mSortedRules = sortedRules();
@VisibleForTesting
protected PreferenceCategory mPreferenceCategory;
public ZenModeAutomaticRulesPreferenceController(Context context, Fragment parent, Lifecycle
lifecycle) {
super(context, KEY, parent, lifecycle);
}
@Override
public String getPreferenceKey() {
return KEY_AUTOMATIC_RULES;
return KEY;
}
@Override
@@ -59,40 +62,14 @@ public class ZenModeAutomaticRulesPreferenceController extends
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();
mPreferenceCategory.removeAll();
Map.Entry<String, AutomaticZenRule>[] sortedRules = sortedRules();
for (Map.Entry<String, AutomaticZenRule> sortedRule : sortedRules) {
ZenRulePreference pref = new ZenRulePreference(mPreferenceCategory.getContext(),
sortedRule, mParent, mMetricsFeatureProvider);
mPreferenceCategory.addPreference(pref);
}
}
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

@@ -28,29 +28,27 @@ import com.android.settings.search.Indexable;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
import java.util.List;
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 static final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
ZenServiceListing serviceListing = new ZenServiceListing(getContext(), CONFIG);
serviceListing.reloadApprovedServices();
return buildPreferenceControllers(context, this, serviceListing);
return buildPreferenceControllers(context, this, serviceListing, getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Fragment parent, ZenServiceListing serviceListing) {
Fragment parent, ZenServiceListing serviceListing, Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeAddAutomaticRulePreferenceController(context, KEY_ADD_RULE,
parent, serviceListing));
controllers.add(new ZenModeAutomaticRulesPreferenceController(context,
KEY_AUTOMATIC_RULES, parent));
controllers.add(new ZenModeAddAutomaticRulePreferenceController(context, parent,
serviceListing, lifecycle));
controllers.add(new ZenModeAutomaticRulesPreferenceController(context, parent, lifecycle));
return controllers;
}
@@ -94,15 +92,15 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase {
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_ADD_RULE);
keys.add(KEY_AUTOMATIC_RULES);
keys.add(ZenModeAddAutomaticRulePreferenceController.KEY);
keys.add(ZenModeAutomaticRulesPreferenceController.KEY);
return keys;
}
@Override
public List<AbstractPreferenceController> getPreferenceControllers(
Context context) {
return buildPreferenceControllers(context, null, null);
return buildPreferenceControllers(context, null, null, null);
}
};
}

View File

@@ -22,6 +22,7 @@ import android.support.v7.preference.Preference;
import android.view.View;
import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.core.PreferenceControllerMixin;
@@ -57,15 +58,21 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
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));
mZenButtonOn.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, true);
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));
mZenButtonOff.setOnClickListener(v -> {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, false);
mBackend.setZenMode(Settings.Global.ZEN_MODE_OFF);
});
}
updateButtons();

View File

@@ -60,16 +60,6 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
return mEvent != null;
}
@Override
protected String getZenModeDependency() {
return null;
}
@Override
protected int getEnabledToastText() {
return R.string.zen_event_rule_enabled_toast;
}
@Override
public void onResume() {
super.onResume();
@@ -89,7 +79,14 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
R.string.zen_event_rule_enabled_toast, getLifecycle());
controllers.add(mHeader);
controllers.add(mSwitch);
return controllers;
}
private void reloadCalendar() {

View File

@@ -24,6 +24,7 @@ import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeEventsPreferenceController extends AbstractZenModePreferenceController
@@ -71,6 +72,8 @@ public class ZenModeEventsPreferenceController extends AbstractZenModePreference
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowEvents=" + allowEvents);
}
mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_EVENTS,
allowEvents);
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_EVENTS, allowEvents);
return true;
}

View File

@@ -23,6 +23,7 @@ import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeRemindersPreferenceController extends AbstractZenModePreferenceController
@@ -67,7 +68,11 @@ public class ZenModeRemindersPreferenceController extends AbstractZenModePrefere
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowReminders = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowReminders=" + allowReminders);
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowReminders=" + allowReminders);
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_REMINDERS, allowReminders);
mBackend.saveSoundPolicy(NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS,
allowReminders);
return true;

View File

@@ -23,6 +23,7 @@ import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePreferenceController
@@ -77,8 +78,11 @@ public class ZenModeRepeatCallersPreferenceController extends AbstractZenModePre
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean allowRepeatCallers = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowRepeatCallers="
+ allowRepeatCallers);
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowRepeatCallers=" + allowRepeatCallers);
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_REPEAT_CALLS, allowRepeatCallers);
mBackend.saveSoundPolicy(Policy.PRIORITY_CATEGORY_REPEAT_CALLERS, allowRepeatCallers);
return true;
}

View File

@@ -16,62 +16,43 @@
package com.android.settings.notification;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.Fragment;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.service.notification.ConditionProviderService;
import android.support.v7.preference.DropDownPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceScreen;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Switch;
import android.widget.Toast;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.widget.SwitchBar;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
implements SwitchBar.OnSwitchChangeListener {
protected static final String TAG = ZenModeSettingsBase.TAG;
protected static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
private static final String KEY_RULE_NAME = "rule_name";
private static final String KEY_ZEN_MODE = "zen_mode";
protected Context mContext;
protected boolean mDisableListeners;
protected AutomaticZenRule mRule;
protected String mId;
private boolean mDeleting;
private Preference mRuleName;
private SwitchBar mSwitchBar;
private DropDownPreference mZenMode;
private Toast mEnabledToast;
protected ZenAutomaticRuleHeaderPreferenceController mHeader;
protected ZenAutomaticRuleSwitchPreferenceController mSwitch;
abstract protected void onCreateInternal();
abstract protected boolean setRule(AutomaticZenRule rule);
abstract protected String getZenModeDependency();
abstract protected void updateControlsInternal();
abstract protected int getEnabledToastText();
@Override
public void onCreate(Bundle icicle) {
@@ -99,8 +80,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
super.onCreate(icicle);
setHasOptionsMenu(true);
onCreateInternal();
final PreferenceScreen root = getPreferenceScreen();
@@ -112,37 +91,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
return true;
}
});
mZenMode = (DropDownPreference) root.findPreference(KEY_ZEN_MODE);
mZenMode.setEntries(new CharSequence[] {
getString(R.string.zen_mode_option_important_interruptions),
getString(R.string.zen_mode_option_alarms),
getString(R.string.zen_mode_option_no_interruptions),
});
mZenMode.setEntryValues(new CharSequence[] {
Integer.toString(NotificationManager.INTERRUPTION_FILTER_PRIORITY),
Integer.toString(NotificationManager.INTERRUPTION_FILTER_ALARMS),
Integer.toString(NotificationManager.INTERRUPTION_FILTER_NONE),
});
mZenMode.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (mDisableListeners) return false;
final int zenMode = Integer.parseInt((String) newValue);
if (zenMode == mRule.getInterruptionFilter()) return false;
if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode);
mRule.setInterruptionFilter(zenMode);
mBackend.setZenRule(mId, mRule);
return true;
}
});
mZenMode.setOrder(10); // sort at the bottom of the category
mZenMode.setDependency(getZenModeDependency());
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
}
@Override
@@ -155,43 +103,39 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
final SettingsActivity activity = (SettingsActivity) getActivity();
mSwitchBar = activity.getSwitchBar();
mSwitchBar.addOnSwitchChangeListener(this);
mSwitchBar.show();
public int getHelpResource() {
return R.string.help_uri_interruptions;
}
@Override
public void onDestroyView() {
super.onDestroyView();
mSwitchBar.removeOnSwitchChangeListener(this);
mSwitchBar.hide();
/**
* Update state of header preference managed by PreferenceController.
*/
protected void updateHeader() {
final PreferenceScreen screen = getPreferenceScreen();
mSwitch.onResume(mRule,mId);
mSwitch.displayPreference(screen);
updatePreference(mSwitch);
mHeader.onResume(mRule);
mHeader.displayPreference(screen);
updatePreference(mHeader);
}
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked);
if (mDisableListeners) return;
final boolean enabled = isChecked;
if (enabled == mRule.isEnabled()) return;
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ENABLE_RULE, enabled);
if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled);
mRule.setEnabled(enabled);
mBackend.setZenRule(mId, mRule);
if (enabled) {
final int toastText = getEnabledToastText();
if (toastText != 0) {
mEnabledToast = Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT);
mEnabledToast.show();
}
} else {
if (mEnabledToast != null) {
mEnabledToast.cancel();
}
private void updatePreference(AbstractPreferenceController controller) {
final PreferenceScreen screen = getPreferenceScreen();
if (!controller.isAvailable()) {
return;
}
final String key = controller.getPreferenceKey();
final Preference preference = screen.findPreference(key);
if (preference == null) {
Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
key, controller.getClass().getSimpleName()));
return;
}
controller.updateState(preference);
}
protected void updateRule(Uri newConditionId) {
@@ -207,33 +151,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
if (DEBUG) Log.d(TAG, "onCreateOptionsMenu");
inflater.inflate(R.menu.zen_mode_rule, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (DEBUG) Log.d(TAG, "onOptionsItemSelected " + item.getItemId());
if (item.getItemId() == R.id.delete) {
mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_DELETE_RULE);
showDeleteRuleDialog();
return true;
}
return super.onOptionsItemSelected(item);
}
private void showRuleNameDialog() {
new ZenRuleNameDialog(mContext, mRule.getName(), null) {
@Override
public void onOk(String ruleName) {
mRule.setName(ruleName);
mBackend.setZenRule(mId, mRule);
}
}.show();
}
private boolean refreshRuleOrFinish() {
mRule = getZenRule();
if (DEBUG) Log.d(TAG, "mRule=" + mRule);
@@ -244,42 +161,22 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
return false;
}
private void showDeleteRuleDialog() {
final AlertDialog dialog = new AlertDialog.Builder(mContext)
.setMessage(getString(R.string.zen_mode_delete_rule_confirmation, mRule.getName()))
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.zen_mode_delete_rule_button, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mMetricsFeatureProvider.action(mContext,
MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
mDeleting = true;
mBackend.removeZenRule(mId);
}
})
.show();
final View messageView = dialog.findViewById(android.R.id.message);
if (messageView != null) {
messageView.setTextDirection(View.TEXT_DIRECTION_LOCALE);
}
private void showRuleNameDialog() {
ZenRuleNameDialog.show(this, mRule.getName(), null, new RuleNameChangeListener());
}
private void toastAndFinish() {
if (!mDeleting) {
Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
.show();
}
getActivity().finish();
}
private void updateRuleName() {
Activity activity = getActivity();
if (activity != null) {
activity.setTitle(mRule.getName());
if (mRule != null) {
mRuleName.setSummary(mRule.getName());
} else {
if (DEBUG) Log.d(TAG, "updateRuleName - activity title and mRuleName "
+ "not updated; getActivity() returned null");
if (DEBUG) Log.d(TAG, "updateRuleName - mRuleName "
+ "not updated; mRuleName returned null");
}
}
@@ -291,10 +188,19 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase
mDisableListeners = true;
updateRuleName();
updateControlsInternal();
mZenMode.setValue(Integer.toString(mRule.getInterruptionFilter()));
if (mSwitchBar != null) {
mSwitchBar.setChecked(mRule.isEnabled());
}
updateHeader();
mDisableListeners = false;
}
public class RuleNameChangeListener implements ZenRuleNameDialog.PositiveClickListener {
public RuleNameChangeListener() {}
@Override
public void onOk(String ruleName, Fragment parent) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mBackend.setZenRule(mId, mRule);
}
}
}

View File

@@ -42,6 +42,7 @@ import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
@@ -76,21 +77,6 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
return R.xml.zen_mode_schedule_rule_settings;
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
return null;
}
@Override
protected String getZenModeDependency() {
return mDays.getKey();
}
@Override
protected int getEnabledToastText() {
return R.string.zen_schedule_rule_enabled_toast;
}
@Override
protected void onCreateInternal() {
final PreferenceScreen root = getPreferenceScreen();
@@ -208,6 +194,20 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
updateEndSummary();
}
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
R.string.zen_schedule_rule_enabled_toast, getLifecycle());
controllers.add(mHeader);
controllers.add(mSwitch);
return controllers;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE;

View File

@@ -22,6 +22,7 @@ import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOffPreferenceController extends
@@ -56,8 +57,11 @@ public class ZenModeScreenOffPreferenceController extends
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOff="
+ !bypass);
if (ZenModeSettingsBase.DEBUG) {
Log.d(TAG, "onPrefChange allowWhenScreenOff=" + bypass);
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_OFF, bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_OFF, bypass);
return true;
}

View File

@@ -22,6 +22,7 @@ import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeScreenOnPreferenceController extends
@@ -57,8 +58,9 @@ public class ZenModeScreenOnPreferenceController extends
public boolean onPreferenceChange(Preference preference, Object newValue) {
final boolean bypass = (Boolean) newValue;
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allowWhenScreenOn="
+ !bypass);
+ bypass);
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_WHEN_SCREEN_ON, bypass);
mBackend.saveVisualEffectsPolicy(Policy.SUPPRESSED_EFFECT_SCREEN_ON, bypass);
return true;
}

View File

@@ -17,73 +17,103 @@
package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.os.Bundle;
import android.service.notification.ZenModeConfig;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public abstract class ZenRuleNameDialog {
private static final String TAG = "ZenRuleNameDialog";
private static final boolean DEBUG = ZenModeSettings.DEBUG;
public class ZenRuleNameDialog extends InstrumentedDialogFragment {
protected static final String TAG = "ZenRuleNameDialog";
private static final String EXTRA_ZEN_RULE_NAME = "zen_rule_name";
private static final String EXTRA_CONDITION_ID = "extra_zen_condition_id";
protected static PositiveClickListener mPositiveClickListener;
private final AlertDialog mDialog;
private final EditText mEditText;
private final CharSequence mOriginalRuleName;
private final boolean mIsNew;
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_RULE_NAME_DIALOG;
}
public ZenRuleNameDialog(Context context, CharSequence ruleName, Uri conditionId) {
mIsNew = ruleName == null;
mOriginalRuleName = ruleName;
/**
* The interface we expect a listener to implement.
*/
public interface PositiveClickListener {
void onOk(String newName, Fragment parent);
}
public static void show(Fragment parent, String ruleName, Uri conditionId, PositiveClickListener
listener) {
final Bundle args = new Bundle();
args.putString(EXTRA_ZEN_RULE_NAME, ruleName);
args.putParcelable(EXTRA_CONDITION_ID, conditionId);
mPositiveClickListener = listener;
ZenRuleNameDialog dialog = new ZenRuleNameDialog();
dialog.setArguments(args);
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(), TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle arguments = getArguments();
Uri conditionId = arguments.getParcelable(EXTRA_CONDITION_ID);
String ruleName = arguments.getString(EXTRA_ZEN_RULE_NAME);
boolean isNew = ruleName == null;
CharSequence originalRuleName = ruleName;
Context context = getContext();
final View v = LayoutInflater.from(context).inflate(R.layout.zen_rule_name, null,
false);
mEditText = (EditText) v.findViewById(R.id.zen_mode_rule_name);
if (!mIsNew) {
mEditText.setText(ruleName);
EditText editText = (EditText) v.findViewById(R.id.zen_mode_rule_name);
if (!isNew) {
// set text to current rule name
editText.setText(ruleName);
// move cursor to end of text
editText.setSelection(editText.getText().length());
}
mEditText.setSelectAllOnFocus(true);
mDialog = new AlertDialog.Builder(context)
.setTitle(getTitleResource(conditionId))
editText.setSelectAllOnFocus(true);
return new AlertDialog.Builder(context)
.setTitle(getTitleResource(conditionId, isNew))
.setView(v)
.setPositiveButton(mIsNew ? R.string.zen_mode_add : R.string.okay,
.setPositiveButton(isNew ? R.string.zen_mode_add : R.string.okay,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
final String newName = trimmedText();
if (TextUtils.isEmpty(newName)) {
return;
}
if (!mIsNew && mOriginalRuleName != null
&& mOriginalRuleName.equals(newName)) {
return; // no change to an existing rule, just dismiss
}
onOk(newName);
}
})
@Override
public void onClick(DialogInterface dialog, int which) {
final String newName = trimmedText(editText);
if (TextUtils.isEmpty(newName)) {
return;
}
if (!isNew && originalRuleName != null
&& originalRuleName.equals(newName)) {
return; // no change to an existing rule, just dismiss
}
mPositiveClickListener.onOk(newName, getTargetFragment());
}
})
.setNegativeButton(R.string.cancel, null)
.create();
}
abstract public void onOk(String ruleName);
public void show() {
mDialog.show();
private String trimmedText(EditText editText) {
return editText.getText() == null ? null : editText.getText().toString().trim();
}
private String trimmedText() {
return mEditText.getText() == null ? null : mEditText.getText().toString().trim();
}
private int getTitleResource(Uri conditionId) {
private int getTitleResource(Uri conditionId, boolean isNew) {
final boolean isEvent = ZenModeConfig.isValidEventConditionId(conditionId);
final boolean isTime = ZenModeConfig.isValidScheduleConditionId(conditionId);
int titleResource = R.string.zen_mode_rule_name;
if (mIsNew) {
if (isNew) {
if (isEvent) {
titleResource = R.string.zen_mode_add_event_rule;
} else if (isTime) {

View File

@@ -16,23 +16,21 @@
package com.android.settings.notification;
import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.Fragment;
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.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.utils.ManagedServiceSettings;
import com.android.settings.utils.ZenServiceListing;
import com.android.settingslib.TwoTargetPreference;
@@ -45,16 +43,17 @@ public class ZenRulePreference extends TwoTargetPreference {
final CharSequence mName;
final String mId;
boolean appExists;
final PreferenceCategory mParent;
final Fragment mParent;
final Preference mPref;
final Context mContext;
final ZenModeBackend mBackend;
final ZenServiceListing mServiceListing;
final PackageManager mPm;
final MetricsFeatureProvider mMetricsFeatureProvider;
public ZenRulePreference(Context context,
final Map.Entry<String, AutomaticZenRule> ruleEntry,
PreferenceCategory prefCategory) {
Fragment parent, MetricsFeatureProvider metricsProvider) {
super(context);
mBackend = ZenModeBackend.getInstance(context);
@@ -62,17 +61,22 @@ public class ZenRulePreference extends TwoTargetPreference {
final AutomaticZenRule rule = ruleEntry.getValue();
mName = rule.getName();
mId = ruleEntry.getKey();
mParent = prefCategory;
mParent = parent;
mPm = mContext.getPackageManager();
mServiceListing = new ZenServiceListing(mContext, CONFIG);
mServiceListing.reloadApprovedServices();
mPref = this;
mMetricsFeatureProvider = metricsProvider;
setAttributes(rule);
}
@Override
protected int getSecondTargetResId() {
if (mId != null && ZenModeConfig.DEFAULT_RULE_IDS.contains(mId)) {
return 0;
}
return R.layout.zen_rule_widget;
}
@@ -89,25 +93,21 @@ public class ZenRulePreference extends TwoTargetPreference {
private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
showDeleteRuleDialog(mId, mName, mParent, mPref);
showDeleteRuleDialog(mParent, mId, mName.toString());
}
};
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();
private void showDeleteRuleDialog(final Fragment parent, final String ruleId,
final String ruleName) {
ZenDeleteRuleDialog.show(parent, ruleName, ruleId,
new ZenDeleteRuleDialog.PositiveClickListener() {
@Override
public void onOk(String id) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
mBackend.removeZenRule(id);
}
});
}
protected void setAttributes(AutomaticZenRule rule) {
@@ -141,26 +141,8 @@ public class ZenRulePreference extends TwoTargetPreference {
private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
CharSequence providerLabel) {
final String mode = computeZenModeCaption(mContext.getResources(),
rule.getInterruptionFilter());
final String ruleState = (rule == null || !rule.isEnabled())
return (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;
}
: mContext.getResources().getString(R.string.switch_on_text);
}
}

View File

@@ -16,16 +16,20 @@
package com.android.settings.notification;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.app.NotificationManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.service.notification.ZenModeConfig;
import android.util.Log;
import android.view.LayoutInflater;
@@ -35,6 +39,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.utils.ZenServiceListing;
import java.lang.ref.WeakReference;
@@ -43,24 +48,48 @@ import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public abstract class ZenRuleSelectionDialog {
public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
private static final String TAG = "ZenRuleSelectionDialog";
private static final boolean DEBUG = ZenModeSettings.DEBUG;
private final Context mContext;
private final PackageManager mPm;
private NotificationManager mNm;
private final AlertDialog mDialog;
private final LinearLayout mRuleContainer;
private final ZenServiceListing mServiceListing;
private static ZenServiceListing mServiceListing;
protected static PositiveClickListener mPositiveClickListener;
public ZenRuleSelectionDialog(Context context, ZenServiceListing serviceListing) {
private static Context mContext;
private static PackageManager mPm;
private static NotificationManager mNm;
private LinearLayout mRuleContainer;
/**
* The interface we expect a listener to implement.
*/
public interface PositiveClickListener {
void onSystemRuleSelected(ZenRuleInfo ruleInfo, Fragment parent);
void onExternalRuleSelected(ZenRuleInfo ruleInfo, Fragment parent);
}
@Override
public int getMetricsCategory() {
return MetricsEvent.NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG;
}
public static void show(Context context, Fragment parent, PositiveClickListener
listener, ZenServiceListing serviceListing) {
mPositiveClickListener = listener;
mContext = context;
mPm = context.getPackageManager();
mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mPm = mContext.getPackageManager();
mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
mServiceListing = serviceListing;
final View v =
LayoutInflater.from(context).inflate(R.layout.zen_rule_type_selection, null, false);
ZenRuleSelectionDialog dialog = new ZenRuleSelectionDialog();
dialog.setTargetFragment(parent, 0);
dialog.show(parent.getFragmentManager(), TAG);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View v = LayoutInflater.from(getContext()).inflate(R.layout.zen_rule_type_selection,
null, false);
mRuleContainer = (LinearLayout) v.findViewById(R.id.rule_container);
if (mServiceListing != null) {
@@ -69,28 +98,21 @@ public abstract class ZenRuleSelectionDialog {
mServiceListing.addZenCallback(mServiceListingCallback);
mServiceListing.reloadApprovedServices();
}
mDialog = new AlertDialog.Builder(context)
return new AlertDialog.Builder(getContext())
.setTitle(R.string.zen_mode_choose_rule_type)
.setView(v)
.setOnDismissListener(new OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
if (mServiceListing != null) {
mServiceListing.removeZenCallback(mServiceListingCallback);
}
}
})
.setNegativeButton(R.string.cancel, null)
.create();
}
public void show() {
mDialog.show();
@Override
public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
if (mServiceListing != null) {
mServiceListing.removeZenCallback(mServiceListingCallback);
}
}
abstract public void onSystemRuleSelected(ZenRuleInfo ruleInfo);
abstract public void onExternalRuleSelected(ZenRuleInfo ruleInfo);
private void bindType(final ZenRuleInfo ri) {
try {
ApplicationInfo info = mPm.getApplicationInfo(ri.packageName, 0);
@@ -108,11 +130,11 @@ public abstract class ZenRuleSelectionDialog {
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
dismiss();
if (ri.isSystem) {
onSystemRuleSelected(ri);
mPositiveClickListener.onSystemRuleSelected(ri, getTargetFragment());
} else {
onExternalRuleSelected(ri);
mPositiveClickListener.onExternalRuleSelected(ri, getTargetFragment());
}
}
});

View File

@@ -18,6 +18,7 @@ package com.android.settings;
import static com.android.settings.DeviceInfoSettings.NON_SIM_PREFERENCES_COUNT;
import static com.android.settings.DeviceInfoSettings.SIM_PREFERENCES_COUNT;
import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
@@ -28,6 +29,7 @@ import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemProperties;
import android.support.v7.preference.PreferenceScreen;
import android.telephony.TelephonyManager;
@@ -118,6 +120,19 @@ public class DeviceInfoSettingsTest {
assertThat(keys).containsAllIn(niks);
}
@Test
@Config(shadows = {SettingsShadowResources.SettingsShadowTheme.class,
SettingsShadowSystemProperties.class})
public void onCreate_fromSearch_shouldNotOverrideInitialExpandedCount() {
final Bundle args = new Bundle();
args.putString(EXTRA_FRAGMENT_ARG_KEY, "search_key");
mSettings.setArguments(args);
mSettings.onCreate(null /* icicle */);
verify(mScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
}
@Test
@Config(shadows = {SettingsShadowResources.SettingsShadowTheme.class,
SettingsShadowSystemProperties.class})

View File

@@ -0,0 +1,191 @@
/*
* 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 static junit.framework.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.AutomaticZenRule;
import android.app.Fragment;
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ZenModeAutomaticRulesPreferenceControllerTest {
private ZenModeAutomaticRulesPreferenceController mController;
private final String GENERIC_RULE_NAME = "test";
final String DEFAULT_ID_1 = "DEFAULT_1";
final String DEFAULT_ID_2 = "DEFAULT_2";
private final List<String> mDefaultIds = Arrays.asList(DEFAULT_ID_1, DEFAULT_ID_2);
@Mock
private ZenModeBackend mBackend;
@Mock
private NotificationManager mNotificationManager;
@Mock
private PreferenceCategory mockPref;
@Mock
private NotificationManager.Policy mPolicy;
@Mock
private PreferenceScreen mPreferenceScreen;
private Context mContext;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
mContext = shadowApplication.getApplicationContext();
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
mController = new ZenModeAutomaticRulesPreferenceController(mContext, mock(Fragment.class),
mock(Lifecycle.class));
ReflectionHelpers.setField(mController, "mBackend", mBackend);
ReflectionHelpers.setField(mController, "DEFAULT_RULE_IDS", mDefaultIds);
when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
mockPref);
mController.displayPreference(mPreferenceScreen);
}
@Test
public void updateState_checkRuleOrderingDescending() {
final int NUM_RULES = 4;
when(mNotificationManager.getAutomaticZenRules()).thenReturn(
mockAutoZenRulesDecreasingCreationTime(NUM_RULES));
Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
assertEquals(NUM_RULES, rules.length);
// check ordering, most recent should be at the bottom/end (ie higher creation time)
for (int i = 0; i < NUM_RULES; i++) {
assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i].getKey());
}
}
@Test
public void updateState_checkRuleOrderingAscending() {
final int NUM_RULES = 4;
when(mNotificationManager.getAutomaticZenRules()).thenReturn(
mockAutoZenRulesAscendingCreationTime(NUM_RULES));
Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
assertEquals(NUM_RULES, rules.length);
// check ordering, most recent should be at the bottom/end (ie higher creation time)
for (int i = 0; i < NUM_RULES; i++) {
assertEquals(GENERIC_RULE_NAME + i, rules[i].getKey());
}
}
@Test
public void updateState_checkRuleOrderingDescending_withDefaultRules() {
final int NUM_RULES = 4;
Map<String, AutomaticZenRule> ruleMap = mockAutoZenRulesDecreasingCreationTime(NUM_RULES);
ruleMap.put(DEFAULT_ID_2, new AutomaticZenRule("DEFAULT_1_NAME", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 20));
ruleMap.put(DEFAULT_ID_1, new AutomaticZenRule("DEFAULT_1_NAME", null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 10));
when(mNotificationManager.getAutomaticZenRules()).thenReturn(ruleMap);
Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
assertEquals(NUM_RULES + 2, rules.length);
assertEquals(rules[0].getKey(), DEFAULT_ID_1);
assertEquals(rules[1].getKey(), DEFAULT_ID_2);
// NON-DEFAULT RULES check ordering, most recent at the bottom/end
for (int i = 0; i < NUM_RULES; i++) {
assertEquals(GENERIC_RULE_NAME + (NUM_RULES - 1 - i), rules[i + 2].getKey());
}
}
@Test
public void updateState_checkRuleOrderingMix() {
final int NUM_RULES = 4;
// map with creation times: 0, 2, 4, 6
Map<String,AutomaticZenRule> rMap = mockAutoZenRulesAscendingCreationTime(NUM_RULES);
final String insertedRule1 = "insertedRule1";
rMap.put(insertedRule1, new AutomaticZenRule(insertedRule1, null, null,
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 5));
final String insertedRule2 = "insertedRule2";
rMap.put(insertedRule2, new AutomaticZenRule(insertedRule2, null, null,
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, 3));
// rule map with rule creation times, 0, 2, 4, 6, 5, 3
// sort should create ordering based on creation times: 0, 2, 3, 4, 5, 6
when(mNotificationManager.getAutomaticZenRules()).thenReturn(rMap);
Map.Entry<String, AutomaticZenRule>[] rules = mController.sortedRules();
assertEquals(NUM_RULES + 2, rules.length); // inserted 2 rules
// check ordering of inserted rules
assertEquals(insertedRule1, rules[4].getKey());
assertEquals(insertedRule2, rules[2].getKey());
}
private Map<String, AutomaticZenRule> mockAutoZenRulesAscendingCreationTime(int numRules) {
Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
for (int i = 0; i < numRules; i++) {
ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, i * 2));
}
return ruleMap;
}
private Map<String, AutomaticZenRule> mockAutoZenRulesDecreasingCreationTime(int numRules) {
Map<String, AutomaticZenRule> ruleMap = new HashMap<>();
for (int i = 0; i < numRules; i++) {
ruleMap.put(GENERIC_RULE_NAME + i, new AutomaticZenRule(GENERIC_RULE_NAME + i, null,
null, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, true, numRules - i));
}
return ruleMap;
}
}