diff --git a/res/layout/notif_priority_conversation_preference.xml b/res/layout/notif_priority_conversation_preference.xml
new file mode 100644
index 00000000000..981cd693cfc
--- /dev/null
+++ b/res/layout/notif_priority_conversation_preference.xml
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/zen_mode_settings_button.xml b/res/layout/zen_mode_settings_button.xml
index 49aa28779aa..72731cc6c2d 100644
--- a/res/layout/zen_mode_settings_button.xml
+++ b/res/layout/zen_mode_settings_button.xml
@@ -39,7 +39,6 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:paddingTop="@dimen/zen_mode_button_padding_vertical"
android:text="@string/zen_mode_button_turn_on"/>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5c2aafea51d..5ddd838429b 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7757,13 +7757,13 @@
Automatically caption media
-
- Never
+
+ None
-
+
- - 1 enabled
- - %d enabled
+ - 1 schedule set
+ - %d schedules set
@@ -7778,26 +7778,8 @@
Turn on Do Not Disturb
-
- Exceptions
-
-
- Default duration
-
-
- Allow sounds and vibrations from
-
-
- No sound
-
-
- Total Silence
-
-
- No sound except %1$s
-
- No sound except alarms and media
+ Alarms and media sounds can interrupt
Schedules
@@ -7832,15 +7814,6 @@
Use schedule
-
- Priority only
-
-
- Alarms only
-
-
- Total silence
-
%1$s: %2$s
@@ -7853,8 +7826,8 @@
Allow interruptions that make sound
-
- Restrict notifications
+
+ Display options for hidden notifications
No sound from notifications
@@ -7993,7 +7966,7 @@
- Exceptions when Do Not Disturb is on
+ What can interrupt Do Not Disturb
People
@@ -8002,23 +7975,12 @@
Alarms & other interruptions
Schedules
-
- Silenced notifications
+
+ Set duration for Quick Settings
When Do Not Disturb is on, sound and vibration will be muted, except for the items you allow above.
-
- Mute all except
-
- Muted
-
- Not muted
-
- Muted, but allow %1$s
-
- Muted, but allow %1$s and %2$s
-
- Muted, but allow %1$s, %2$s, and %3$s
Custom settings
@@ -8190,11 +8152,11 @@
Allow %1$s to show some notifications as bubbles
- Turn on bubbles
+ Turn on bubbles for device?
- To turn on bubbles for this app, first you need to turn them on for your device. This affects other apps in which you previously turned on bubbles.
+ Turning on bubbles for this app will also turn on bubbles for your device.\n\nThis affects other apps or conversations that are allowed to bubble.
- Turn on for device
+ Turn on
Cancel
@@ -8213,8 +8175,8 @@
Nothing can bubble
Conversations
-
- Excluded
+
+ All conversations can bubble except
Swipe actions
@@ -8444,6 +8406,12 @@
Let the app make sound, vibrate, and/or pop notifications on screen
+
+ Priority
+
+
+ Shows at top of conversation section and appears as a bubble.
+
@@ -8923,19 +8891,15 @@
Allow calls
-
Calls
-
To be sure allowed calls make sound, check whether your device is set to ring, vibrate, or silent.
-
For \u2018%1$s\u2019 incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
Starred contacts
-
- 1 other
@@ -8949,128 +8913,119 @@
Allow messages
-
To be sure allowed messages make sound, check whether your device is set to ring, vibrate, or silent.
-
For \u2018%1$s\u2019 incoming messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
-
SMS, MMS, and messaging apps
From anyone
-
From contacts only
-
From starred contacts only
From starred contacts and repeat callers
-
From contacts and repeat callers
-
From repeat callers only
None
-
Don\u2019t allow any calls
-
Don\u2019t allow any messages
Alarms
-
From timers, alarms, security systems, and other apps
-
alarms
Media sounds
-
From videos, games, and other media
-
media
Touch sounds
-
From your keyboard and other buttons
-
touch sounds
Reminders
-
From tasks and reminders
-
reminders
Events
-
From upcoming calendar events
-
-
- Allow apps to override
-
-
- App exceptions
-
-
- No apps can override Do Not Disturb
-
-
-
- - No apps can override Do Not Disturb
- - Notifications from 1 app can override Do Not Disturb
- - Notifications from %1$d apps can override Do Not Disturb
-
-
events
-
- anyone
+
+ Allow apps to override
+
+ No apps can interrupt
+
+
+ - %s can interrupt
+ - %s can interrupt
+
+
+ %d more
+
+ App exceptions
-
- contacts
+
+
+ - %s can interrupt
+ - %s can interrupt
+
+
+ Nothing can interrupt
+
+ %d more
-
- starred contacts
+
+ No one can interrupt
+
+ Some people can interrupt
+
+ All people can interrupt
Repeat callers
-
-
- repeat callers
-
Allow repeat callers
-
+
+ anyone
+
+ contacts
+
+ starred contacts
+
+ repeat callers
Allow from %1$s
-
Allow from %1$s and %2$s
-
If the same person calls a second time within a %d minute period
@@ -9079,43 +9034,33 @@
Automatically turn on
-
Never
-
Every night
-
Weeknights
-
Start time
-
End time
-
%s next day
Change to alarms only indefinitely
-
- Change to alarms only for one minute until %2$s
- Change to alarms only for %1$d minutes (until %2$s)
-
- Change to alarms only for one hour until %2$s
- Change to alarms only for %1$d hours until %2$s
-
Change to alarms only until %1$s
-
Change to always interrupt
@@ -11875,6 +11820,51 @@
This choice is no longer valid. Try again.
+
+ Quick controls
+
+
+ quick controls
+
+
+ Cards & passes
+
+
+ cards & passes
+
+
+ Power menu
+
+
+ Power button menu
+
+
+ Show cards & passes
+
+
+ Show quick controls
+
+
+ Show cards, passes, and quick controls
+
+
+ Don\u2019t show any content
+
+
+ Privacy
+
+
+ Show cards and controls when locked
+
+
+ Hide cards and controls when locked
+
+
+ Show quick controls
+
+
+ To access controls for connected devices, hold the Power button
+
diff --git a/res/xml/conversation_notification_settings.xml b/res/xml/conversation_notification_settings.xml
index d0db428f5bc..be1c980a05c 100644
--- a/res/xml/conversation_notification_settings.xml
+++ b/res/xml/conversation_notification_settings.xml
@@ -26,19 +26,11 @@
settings:allowDividerBelow="true"/>
-
-
-
-
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/security_settings_face.xml b/res/xml/security_settings_face.xml
index 858911d6fb9..d450fef4dee 100644
--- a/res/xml/security_settings_face.xml
+++ b/res/xml/security_settings_face.xml
@@ -29,7 +29,7 @@
-
-
@@ -55,26 +54,26 @@
+ settings:initialExpandedChildrenCount="0">
+
+
+
-
-
-
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 3883eba9ebe..1c2952a3b46 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -282,12 +282,12 @@ public class SettingsActivity extends SettingsBaseActivity
launchSettingFragment(initialFragmentName, intent);
}
- final boolean deviceProvisioned = WizardManagerHelper.isDeviceProvisioned(this);
+ final boolean isInSetupWizard = WizardManagerHelper.isAnySetupWizard(getIntent());
final ActionBar actionBar = getActionBar();
if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(deviceProvisioned);
- actionBar.setHomeButtonEnabled(deviceProvisioned);
+ actionBar.setDisplayHomeAsUpEnabled(!isInSetupWizard);
+ actionBar.setHomeButtonEnabled(!isInSetupWizard);
actionBar.setDisplayShowTitleEnabled(true);
}
mSwitchBar = findViewById(R.id.switch_bar);
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
index 9ec1ad1eb74..7e7a748faec 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsKeyguardPreferenceController.java
@@ -25,6 +25,8 @@ import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.Utils;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedSwitchPreference;
/**
* Preference controller for Face settings page controlling the ability to unlock the phone
@@ -53,7 +55,7 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
public boolean isChecked() {
if (!FaceSettings.isAvailable(mContext)) {
return false;
- } else if (adminDisabled()) {
+ } else if (getRestrictingAdmin() != null) {
return false;
}
return Settings.Secure.getIntForUser(mContext.getContentResolver(),
@@ -73,11 +75,12 @@ public class FaceSettingsKeyguardPreferenceController extends FaceSettingsPrefer
@Override
public void updateState(Preference preference) {
+ EnforcedAdmin admin;
super.updateState(preference);
if (!FaceSettings.isAvailable(mContext)) {
preference.setEnabled(false);
- } else if (adminDisabled()) {
- preference.setEnabled(false);
+ } else if ((admin = getRestrictingAdmin()) != null) {
+ ((RestrictedSwitchPreference) preference).setDisabledByAdmin(admin);
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
preference.setEnabled(false);
} else {
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
index cef174d5243..50c45ba86e4 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceController.java
@@ -26,6 +26,8 @@ import android.provider.Settings;
import androidx.preference.Preference;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedSwitchPreference;
public class FaceSettingsLockscreenBypassPreferenceController
extends FaceSettingsPreferenceController {
@@ -60,11 +62,12 @@ public class FaceSettingsLockscreenBypassPreferenceController
@Override
public void updateState(Preference preference) {
+ EnforcedAdmin admin;
super.updateState(preference);
if (!FaceSettings.isAvailable(mContext)) {
preference.setEnabled(false);
- } else if (adminDisabled()) {
- preference.setEnabled(false);
+ } else if ((admin = getRestrictingAdmin()) != null) {
+ ((RestrictedSwitchPreference) preference).setDisabledByAdmin(admin);
} else if (!mFaceManager.hasEnrolledTemplates(getUserId())) {
preference.setEnabled(false);
} else {
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
index 55e093ba79a..3149c353ada 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsPreferenceController.java
@@ -18,9 +18,10 @@ package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.os.UserHandle;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import com.android.settingslib.RestrictedLockUtilsInternal;
/**
* Abstract base class for all face settings toggles.
@@ -41,12 +42,8 @@ public abstract class FaceSettingsPreferenceController extends TogglePreferenceC
return mUserId;
}
- protected boolean adminDisabled() {
- DevicePolicyManager dpm =
- (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
- return dpm != null &&
- (dpm.getKeyguardDisabledFeatures(null, UserHandle.myUserId())
- & DevicePolicyManager.KEYGUARD_DISABLE_FACE)
- != 0;
+ protected EnforcedAdmin getRestrictingAdmin() {
+ return RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
+ mContext, DevicePolicyManager.KEYGUARD_DISABLE_FACE, mUserId);
}
}
diff --git a/src/com/android/settings/display/BrightnessLevelPreferenceController.java b/src/com/android/settings/display/BrightnessLevelPreferenceController.java
index dc24ed0188f..2e545721f68 100644
--- a/src/com/android/settings/display/BrightnessLevelPreferenceController.java
+++ b/src/com/android/settings/display/BrightnessLevelPreferenceController.java
@@ -14,7 +14,8 @@
package com.android.settings.display;
import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MAX;
-import static com.android.settingslib.display.BrightnessUtils.convertLinearToGamma;
+import static com.android.settingslib.display.BrightnessUtils.GAMMA_SPACE_MIN;
+import static com.android.settingslib.display.BrightnessUtils.convertLinearToGammaFloat;
import android.content.ContentResolver;
import android.content.Context;
@@ -52,16 +53,16 @@ public class BrightnessLevelPreferenceController extends AbstractPreferenceContr
private static final Uri BRIGHTNESS_FOR_VR_URI;
private static final Uri BRIGHTNESS_ADJ_URI;
- private final int mMinBrightness;
- private final int mMaxBrightness;
- private final int mMinVrBrightness;
- private final int mMaxVrBrightness;
+ private final float mMinBrightness;
+ private final float mMaxBrightness;
+ private final float mMinVrBrightness;
+ private final float mMaxVrBrightness;
private final ContentResolver mContentResolver;
private Preference mPreference;
static {
- BRIGHTNESS_URI = System.getUriFor(System.SCREEN_BRIGHTNESS);
+ BRIGHTNESS_URI = System.getUriFor(System.SCREEN_BRIGHTNESS_FLOAT);
BRIGHTNESS_FOR_VR_URI = System.getUriFor(System.SCREEN_BRIGHTNESS_FOR_VR);
BRIGHTNESS_ADJ_URI = System.getUriFor(System.SCREEN_AUTO_BRIGHTNESS_ADJ);
}
@@ -80,10 +81,14 @@ public class BrightnessLevelPreferenceController extends AbstractPreferenceContr
lifecycle.addObserver(this);
}
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mMinBrightness = powerManager.getMinimumScreenBrightnessSetting();
- mMaxBrightness = powerManager.getMaximumScreenBrightnessSetting();
- mMinVrBrightness = powerManager.getMinimumScreenBrightnessForVrSetting();
- mMaxVrBrightness = powerManager.getMaximumScreenBrightnessForVrSetting();
+ mMinBrightness = powerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM);
+ mMaxBrightness = powerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM);
+ mMinVrBrightness = powerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR);
+ mMaxVrBrightness = powerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR);
mContentResolver = mContext.getContentResolver();
}
@@ -129,16 +134,15 @@ public class BrightnessLevelPreferenceController extends AbstractPreferenceContr
private double getCurrentBrightness() {
final int value;
if (isInVrMode()) {
- value = convertLinearToGamma(System.getInt(mContentResolver,
- System.SCREEN_BRIGHTNESS_FOR_VR, mMaxBrightness),
+ value = convertLinearToGammaFloat(System.getFloat(mContentResolver,
+ System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, mMaxBrightness),
mMinVrBrightness, mMaxVrBrightness);
} else {
- value = convertLinearToGamma(Settings.System.getInt(mContentResolver,
- System.SCREEN_BRIGHTNESS, mMinBrightness),
+ value = convertLinearToGammaFloat(Settings.System.getFloat(mContentResolver,
+ System.SCREEN_BRIGHTNESS_FLOAT, mMinBrightness),
mMinBrightness, mMaxBrightness);
-
}
- return getPercentage(value, 0, GAMMA_SPACE_MAX);
+ return getPercentage(value, GAMMA_SPACE_MIN, GAMMA_SPACE_MAX);
}
private double getPercentage(double value, int min, int max) {
diff --git a/src/com/android/settings/network/ims/VolteQueryImsState.java b/src/com/android/settings/network/ims/VolteQueryImsState.java
index 1fa72d7fb4d..167b4b13a3e 100644
--- a/src/com/android/settings/network/ims/VolteQueryImsState.java
+++ b/src/com/android/settings/network/ims/VolteQueryImsState.java
@@ -27,10 +27,6 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
-import com.android.ims.ImsManager;
-import com.android.settings.network.SubscriptionUtil;
-import com.android.settings.network.telephony.MobileNetworkUtils;
-
/**
* Controller class for querying Volte status
*/
@@ -66,12 +62,6 @@ public class VolteQueryImsState extends ImsQueryController {
return (new ImsQueryEnhanced4gLteModeUserSetting(subId)).query();
}
- @VisibleForTesting
- ImsManager getImsManager(int subId) {
- return ImsManager.getInstance(mContext,
- SubscriptionUtil.getPhoneId(mContext, subId));
- }
-
/**
* Check whether VoLTE has been provisioned or not on this subscription
*
@@ -101,8 +91,15 @@ public class VolteQueryImsState extends ImsQueryController {
if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
return false;
}
- return isVoLteProvisioned()
- && MobileNetworkUtils.isImsServiceStateReady(getImsManager(mSubId));
+ if (!isVoLteProvisioned()) {
+ return false;
+ }
+ try {
+ return isServiceStateReady(mSubId);
+ } catch (InterruptedException | IllegalArgumentException | ImsException exception) {
+ Log.w(LOG_TAG, "fail to get VoLte service status. subId=" + mSubId, exception);
+ }
+ return false;
}
/**
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index c0df8513281..5ae1fdeaf95 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -204,6 +204,8 @@ public class EnabledNetworkModePreferenceController extends
}
void setPreferenceEntries() {
+ clearAllEntries();
+
switch (getEnabledNetworkType()) {
case ENABLED_NETWORKS_CDMA_CHOICES:
add5gEntry(addNrToLteNetworkType(
@@ -608,6 +610,11 @@ public class EnabledNetworkModePreferenceController extends
return mEntries.toArray(new String[0]);
}
+ private void clearAllEntries() {
+ mEntries.clear();
+ mEntriesValue.clear();
+ }
+
private String[] getEntryValues() {
Integer intArr[] = mEntriesValue.toArray(new Integer[0]);
return Arrays.stream(intArr)
diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java
index 879f17af9e7..d33ba7e1aa3 100644
--- a/src/com/android/settings/notification/app/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/app/BubblePreferenceController.java
@@ -68,7 +68,7 @@ public class BubblePreferenceController extends NotificationPreferenceController
if (isDefaultChannel()) {
return true;
} else {
- return mAppRow != null && mAppRow.allowBubbles;
+ return mAppRow != null;
}
}
return true;
diff --git a/src/com/android/settings/notification/app/ConversationListSettings.java b/src/com/android/settings/notification/app/ConversationListSettings.java
index aaeaa950c8b..1eb997a0db9 100644
--- a/src/com/android/settings/notification/app/ConversationListSettings.java
+++ b/src/com/android/settings/notification/app/ConversationListSettings.java
@@ -18,15 +18,8 @@ package com.android.settings.notification.app;
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
import android.util.Log;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-
-import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.NotificationBackend;
@@ -60,7 +53,7 @@ public class ConversationListSettings extends DashboardFragment {
@Override
protected List createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
- mControllers.add(new ImportantConversationsPreferenceController(context, mBackend));
+ mControllers.add(new PriorityConversationsPreferenceController(context, mBackend));
mControllers.add(new AllConversationsPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
diff --git a/src/com/android/settings/notification/app/ConversationNotificationSettings.java b/src/com/android/settings/notification/app/ConversationNotificationSettings.java
index c5a8e6ee100..210af2086e6 100644
--- a/src/com/android/settings/notification/app/ConversationNotificationSettings.java
+++ b/src/com/android/settings/notification/app/ConversationNotificationSettings.java
@@ -79,18 +79,13 @@ public class ConversationNotificationSettings extends NotificationSettings {
protected List createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
mControllers.add(new ConversationHeaderPreferenceController(context, this));
- mControllers.add(new ConversationImportantPreferenceController(
+ mControllers.add(new ConversationPriorityPreferenceController(
context, mBackend, mDependentFieldListener));
- mControllers.add(new DefaultImportancePreferenceController(
- context, mDependentFieldListener, mBackend));
- mControllers.add(new AddToHomeScreenPreferenceController(context, mBackend));
mControllers.add(new HighImportancePreferenceController(
context, mDependentFieldListener, mBackend));
mControllers.add(new SoundPreferenceController(context, this,
mDependentFieldListener, mBackend));
mControllers.add(new VibrationPreferenceController(context, mBackend));
- mControllers.add(new AppLinkPreferenceController(context));
- mControllers.add(new DescriptionPreferenceController(context));
mControllers.add(new VisibilityPreferenceController(context, new LockPatternUtils(context),
mBackend));
mControllers.add(new LightsPreferenceController(context, mBackend));
diff --git a/src/com/android/settings/notification/app/ConversationPriorityPreference.java b/src/com/android/settings/notification/app/ConversationPriorityPreference.java
new file mode 100644
index 00000000000..ff1dc6c5d91
--- /dev/null
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreference.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2020 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.app;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import android.transition.AutoTransition;
+import android.transition.TransitionManager;
+import android.util.AttributeSet;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.Utils;
+import com.android.settingslib.R;
+
+public class ConversationPriorityPreference extends Preference {
+
+ private boolean mIsConfigurable = true;
+ private int mImportance;
+ private int mOriginalImportance;
+ private boolean mPriorityConversation;
+ private View mSilenceButton;
+ private View mAlertButton;
+ private View mPriorityButton;
+ private Context mContext;
+ Drawable selectedBackground;
+ Drawable unselectedBackground;
+ private static final int BUTTON_ANIM_TIME_MS = 100;
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mContext = context;
+ selectedBackground = mContext.getDrawable(R.drawable.button_border_selected);
+ unselectedBackground = mContext.getDrawable(R.drawable.button_border_unselected);
+ setLayoutResource(R.layout.notif_priority_conversation_preference);
+ }
+
+ public void setImportance(int importance) {
+ mImportance = importance;
+ }
+
+ public void setConfigurable(boolean configurable) {
+ mIsConfigurable = configurable;
+ }
+
+ public void setPriorityConversation(boolean priorityConversation) {
+ mPriorityConversation = priorityConversation;
+ }
+
+ public void setOriginalImportance(int importance) {
+ mOriginalImportance = importance;
+ }
+
+ @Override
+ public void onBindViewHolder(final PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ holder.itemView.setClickable(false);
+
+ mSilenceButton = holder.findViewById(R.id.silence);
+ mAlertButton = holder.findViewById(R.id.alert);
+ mPriorityButton = holder.findViewById(R.id.priority_group);
+
+ if (!mIsConfigurable) {
+ mSilenceButton.setEnabled(false);
+ mAlertButton.setEnabled(false);
+ mPriorityButton.setEnabled(false);
+ }
+
+ updateToggles((ViewGroup) holder.itemView, mImportance, mPriorityConversation,
+ false);
+
+ mSilenceButton.setOnClickListener(v -> {
+ callChangeListener(new Pair(IMPORTANCE_LOW, false));
+ updateToggles((ViewGroup) holder.itemView, IMPORTANCE_LOW, false, true);
+ });
+ mAlertButton.setOnClickListener(v -> {
+ int newImportance = Math.max(mOriginalImportance, IMPORTANCE_DEFAULT);
+ callChangeListener(new Pair(newImportance, false));
+ updateToggles((ViewGroup) holder.itemView, newImportance, false, true);
+ });
+ mPriorityButton.setOnClickListener(v -> {
+ int newImportance = Math.max(mOriginalImportance, IMPORTANCE_DEFAULT);
+ callChangeListener(new Pair(newImportance, true));
+ updateToggles((ViewGroup) holder.itemView, newImportance, true, true);
+ });
+ }
+
+ private ColorStateList getAccentTint() {
+ return Utils.getColorAccent(getContext());
+ }
+
+ private ColorStateList getRegularTint() {
+ return Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
+ }
+
+ void updateToggles(ViewGroup parent, int importance, boolean isPriority,
+ boolean fromUser) {
+ if (fromUser) {
+ AutoTransition transition = new AutoTransition();
+ transition.setDuration(BUTTON_ANIM_TIME_MS);
+ TransitionManager.beginDelayedTransition(parent, transition);
+ }
+
+ ColorStateList colorAccent = getAccentTint();
+ ColorStateList colorNormal = getRegularTint();
+ ImageView silenceIcon = parent.findViewById(R.id.silence_icon);
+ TextView silenceLabel = parent.findViewById(R.id.silence_label);
+ TextView silenceSummary = parent.findViewById(R.id.silence_summary);
+ ImageView alertIcon = parent.findViewById(R.id.alert_icon);
+ TextView alertLabel = parent.findViewById(R.id.alert_label);
+ TextView alertSummary = parent.findViewById(R.id.alert_summary);
+ ImageView priorityIcon = parent.findViewById(R.id.priority_icon);
+ TextView priorityLabel = parent.findViewById(R.id.priority_label);
+ TextView prioritySummary = parent.findViewById(R.id.priority_summary);
+
+ if (importance <= IMPORTANCE_LOW && importance > IMPORTANCE_UNSPECIFIED) {
+ alertSummary.setVisibility(GONE);
+ alertIcon.setImageTintList(colorNormal);
+ alertLabel.setTextColor(colorNormal);
+
+ prioritySummary.setVisibility(GONE);
+ priorityIcon.setImageTintList(colorNormal);
+ priorityLabel.setTextColor(colorNormal);
+
+ silenceIcon.setImageTintList(colorAccent);
+ silenceLabel.setTextColor(colorAccent);
+ silenceSummary.setVisibility(VISIBLE);
+
+ mAlertButton.setBackground(unselectedBackground);
+ mPriorityButton.setBackground(unselectedBackground);
+ mSilenceButton.setBackground(selectedBackground);
+ // a11y service won't always read the newly appearing text in the right order if the
+ // selection happens too soon (readback happens on a different thread as layout). post
+ // the selection to make that conflict less likely
+ parent.post(() -> mSilenceButton.setSelected(true));
+ } else {
+ if (isPriority) {
+ alertSummary.setVisibility(GONE);
+ alertIcon.setImageTintList(colorNormal);
+ alertLabel.setTextColor(colorNormal);
+
+ prioritySummary.setVisibility(VISIBLE);
+ priorityIcon.setImageTintList(colorAccent);
+ priorityLabel.setTextColor(colorAccent);
+
+ silenceIcon.setImageTintList(colorNormal);
+ silenceLabel.setTextColor(colorNormal);
+ silenceSummary.setVisibility(GONE);
+
+ mAlertButton.setBackground(unselectedBackground);
+ mPriorityButton.setBackground(selectedBackground);
+ mSilenceButton.setBackground(unselectedBackground);
+ parent.post(() -> mPriorityButton.setSelected(true));
+ } else {
+ alertSummary.setVisibility(VISIBLE);
+ alertIcon.setImageTintList(colorAccent);
+ alertLabel.setTextColor(colorAccent);
+
+ prioritySummary.setVisibility(GONE);
+ priorityIcon.setImageTintList(colorNormal);
+ priorityLabel.setTextColor(colorNormal);
+
+ silenceIcon.setImageTintList(colorNormal);
+ silenceLabel.setTextColor(colorNormal);
+ silenceSummary.setVisibility(GONE);
+
+ mAlertButton.setBackground(selectedBackground);
+ mPriorityButton.setBackground(unselectedBackground);
+ mSilenceButton.setBackground(unselectedBackground);
+ parent.post(() -> mAlertButton.setSelected(true));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/app/ConversationImportantPreferenceController.java b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
similarity index 63%
rename from src/com/android/settings/notification/app/ConversationImportantPreferenceController.java
rename to src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
index 0b1ee16e8a5..e59f277699f 100644
--- a/src/com/android/settings/notification/app/ConversationImportantPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
@@ -16,25 +16,22 @@
package com.android.settings.notification.app;
-import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
-
import android.content.Context;
-import android.provider.Settings;
+import android.util.Pair;
import androidx.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.RestrictedSwitchPreference;
-public class ConversationImportantPreferenceController extends NotificationPreferenceController
+public class ConversationPriorityPreferenceController extends NotificationPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
- private static final String TAG = "ConvoImpPC";
- private static final String KEY = "important";
+ private static final String TAG = "ConvoPriorityPC";
+ private static final String KEY = "priority";
private final NotificationSettings.DependentFieldListener mDependentFieldListener;
- public ConversationImportantPreferenceController(Context context,
+ public ConversationPriorityPreferenceController(Context context,
NotificationBackend backend, NotificationSettings.DependentFieldListener listener) {
super(context, backend);
mDependentFieldListener = listener;
@@ -58,10 +55,12 @@ public class ConversationImportantPreferenceController extends NotificationPrefe
public void updateState(Preference preference) {
if (mAppRow != null) {
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
- pref.setDisabledByAdmin(mAdmin);
- pref.setChecked(mChannel.isImportantConversation());
- pref.setEnabled(!pref.isDisabledByAdmin());
+ preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
+ ConversationPriorityPreference pref = (ConversationPriorityPreference) preference;
+ pref.setConfigurable(!mChannel.isImportanceLockedByOEM());
+ pref.setImportance(mChannel.getImportance());
+ pref.setOriginalImportance(mChannel.getOriginalImportance());
+ pref.setPriorityConversation(mChannel.isImportantConversation());
}
}
@@ -70,19 +69,21 @@ public class ConversationImportantPreferenceController extends NotificationPrefe
if (mChannel == null) {
return false;
}
- final boolean value = (Boolean) newValue;
- mChannel.setImportantConversation(value);
- if (value && bubbleImportantConversations()) {
+ boolean wasPriorityConversation = mChannel.isImportantConversation();
+
+ final Pair value = (Pair) newValue;
+ mChannel.setImportance(value.first);
+ mChannel.setImportantConversation(value.second);
+
+ if (value.second) {
mChannel.setAllowBubbles(true);
+ } else if (wasPriorityConversation) {
+ mChannel.setAllowBubbles(false);
}
+
mDependentFieldListener.onFieldValueChanged();
saveChannel();
return true;
}
-
- private boolean bubbleImportantConversations() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1) == 1;
- }
}
diff --git a/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java b/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java
deleted file mode 100644
index 616d64a3b46..00000000000
--- a/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 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.app;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-
-import android.app.NotificationChannel;
-import android.content.Context;
-
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.RestrictedSwitchPreference;
-
-public class DefaultImportancePreferenceController extends NotificationPreferenceController
- implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
-
- private static final String KEY = "alerting";
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
-
- public DefaultImportancePreferenceController(Context context,
- NotificationSettings.DependentFieldListener dependentFieldListener,
- NotificationBackend backend) {
- super(context, backend);
- mDependentFieldListener = dependentFieldListener;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
- }
- if (mChannel == null) {
- return false;
- }
- if (isDefaultChannel()) {
- return false;
- }
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- if (mAppRow != null && mChannel != null) {
- preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
-
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
- pref.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT);
- }
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (mChannel != null) {
- final boolean checked = (boolean) newValue;
-
- mChannel.setImportance(checked ? IMPORTANCE_DEFAULT : IMPORTANCE_LOW);
- mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- saveChannel();
- mDependentFieldListener.onFieldValueChanged();
- }
- return true;
- }
-}
diff --git a/src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
similarity index 94%
rename from src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java
rename to src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
index 2089d9d3bbe..ed12d7dd7ed 100644
--- a/src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java
+++ b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
@@ -28,14 +28,14 @@ import com.android.settings.notification.NotificationBackend;
import java.util.Collections;
import java.util.List;
-public class ImportantConversationsPreferenceController extends
+public class PriorityConversationsPreferenceController extends
ConversationListPreferenceController {
private static final String KEY = "important_conversations";
private static final String LIST_KEY = "important_conversations_list";
private List mConversations;
- public ImportantConversationsPreferenceController(Context context,
+ public PriorityConversationsPreferenceController(Context context,
NotificationBackend backend) {
super(context, backend);
}
diff --git a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
index a93fa1b9856..7459394d701 100644
--- a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
@@ -1,19 +1,53 @@
package com.android.settings.notification.zen;
+import android.app.Application;
+import android.app.NotificationChannel;
import android.content.Context;
-import android.os.UserHandle;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.text.TextUtils;
+import androidx.core.text.BidiFormatter;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
-public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController {
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Apps
+ */
+public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController
+ implements PreferenceControllerMixin {
protected static final String KEY = "zen_mode_behavior_apps";
+
+ @VisibleForTesting protected Preference mPreference;
+ private ApplicationsState.Session mAppSession;
private NotificationBackend mNotificationBackend = new NotificationBackend();
- public ZenModeBypassingAppsPreferenceController(Context context, Lifecycle lifecycle) {
+ private String mSummary;
+
+ public ZenModeBypassingAppsPreferenceController(Context context, Application app,
+ Fragment host, Lifecycle lifecycle) {
+ this(context, app == null ? null : ApplicationsState.getInstance(app), host, lifecycle);
+ }
+
+ private ZenModeBypassingAppsPreferenceController(Context context, ApplicationsState appState,
+ Fragment host, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
+ if (appState != null && host != null) {
+ mAppSession = appState.newSession(mAppSessionCallbacks, host.getLifecycle());
+ }
}
@Override
@@ -22,13 +56,125 @@ public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePre
}
@Override
- public String getSummary() {
- final int channelsBypassing =
- mNotificationBackend.getNumAppsBypassingDnd(UserHandle.getCallingUserId());
- if (channelsBypassing == 0) {
- return mContext.getResources().getString(R.string.zen_mode_bypassing_apps_subtext_none);
- }
- return mContext.getResources().getQuantityString(R.plurals.zen_mode_bypassing_apps_subtext,
- channelsBypassing, channelsBypassing);
+ public String getPreferenceKey() {
+ return KEY;
}
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPreference = screen.findPreference(KEY);
+ updateAppsBypassingDndSummaryText();
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public String getSummary() {
+ return mSummary;
+ }
+
+ private void updateAppsBypassingDndSummaryText() {
+ if (mAppSession == null) {
+ return;
+ }
+
+ ApplicationsState.AppFilter filter = ApplicationsState.FILTER_ALL_ENABLED;
+ List apps = mAppSession.rebuild(filter,
+ ApplicationsState.ALPHA_COMPARATOR);
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @VisibleForTesting
+ void updateAppsBypassingDndSummaryText(List apps) {
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ case Settings.Global.ZEN_MODE_ALARMS:
+ // users cannot change their DND settings when an app puts the device total
+ // silence or alarms only (both deprecated) modes
+ mPreference.setEnabled(false);
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ return;
+ default:
+ mPreference.setEnabled(true);
+ }
+
+ if (apps == null) {
+ return;
+ }
+
+ List appsBypassingDnd = new ArrayList<>();
+ for (ApplicationsState.AppEntry entry : apps) {
+ String pkg = entry.info.packageName;
+ for (NotificationChannel channel : mNotificationBackend
+ .getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList()) {
+ if (!TextUtils.isEmpty(channel.getConversationId())) {
+ // conversation channels that bypass dnd will be shown on the People page
+ continue;
+ }
+ appsBypassingDnd.add(BidiFormatter.getInstance().unicodeWrap(entry.label));
+ continue;
+ }
+ }
+
+ if (appsBypassingDnd.size() == 0) {
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ refreshSummary(mPreference);
+ return;
+ }
+
+ List displayAppsBypassing = new ArrayList<>();
+ if (appsBypassingDnd.size() <= 2) {
+ displayAppsBypassing = appsBypassingDnd;
+ } else {
+ displayAppsBypassing.add(appsBypassingDnd.get(0));
+ displayAppsBypassing.add(appsBypassingDnd.get(1));
+ displayAppsBypassing.add(mContext.getResources().getString(
+ R.string.zen_mode_apps_bypassing_list_count,
+ appsBypassingDnd.size() - 2));
+ }
+ mSummary = mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_bypassing_apps_subtext,
+ appsBypassingDnd.size(),
+ ListFormatter.getInstance().format(displayAppsBypassing));
+ refreshSummary(mPreference);
+ }
+
+ private final ApplicationsState.Callbacks mAppSessionCallbacks =
+ new ApplicationsState.Callbacks() {
+
+ @Override
+ public void onRunningStateChanged(boolean running) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onPackageListChanged() {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onRebuildComplete(ArrayList apps) {
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @Override
+ public void onPackageIconChanged() { }
+
+ @Override
+ public void onPackageSizeChanged(String packageName) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onAllSizesComputed() { }
+
+ @Override
+ public void onLauncherInfoChanged() { }
+
+ @Override
+ public void onLoadEntriesCompleted() {
+ updateAppsBypassingDndSummaryText();
+ }
+ };
}
diff --git a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
index a48c93d5d6b..cb185dd6c4d 100644
--- a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
@@ -16,25 +16,33 @@
package com.android.settings.notification.zen;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > People
+ */
public class ZenModePeoplePreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
private final String KEY;
- private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModePeoplePreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, key, lifecycle);
KEY = key;
- mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
@@ -60,8 +68,28 @@ public class ZenModePeoplePreferenceController extends
break;
default:
preference.setEnabled(true);
- // TODO: How do all of the people options roll up into the summary?
- //preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
+ preference.setSummary(getPeopleSummary());
+ }
+ }
+
+ private String getPeopleSummary() {
+ final int callersAllowed = mBackend.getPriorityCallSenders();
+ final int messagesAllowed = mBackend.getPriorityMessageSenders();
+ final int conversationsAllowed = mBackend.getPriorityConversationSenders();
+ final boolean areRepeatCallersAllowed =
+ mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_REPEAT_CALLERS);
+
+ if (callersAllowed == PRIORITY_SENDERS_ANY
+ && messagesAllowed == PRIORITY_SENDERS_ANY
+ && conversationsAllowed == CONVERSATION_SENDERS_ANYONE) {
+ return mContext.getResources().getString(R.string.zen_mode_people_all);
+ } else if (callersAllowed == ZenModeBackend.SOURCE_NONE
+ && messagesAllowed == ZenModeBackend.SOURCE_NONE
+ && conversationsAllowed == CONVERSATION_SENDERS_NONE
+ && !areRepeatCallersAllowed) {
+ return mContext.getResources().getString(R.string.zen_mode_people_none);
+ } else {
+ return mContext.getResources().getString(R.string.zen_mode_people_some);
}
}
}
diff --git a/src/com/android/settings/notification/zen/ZenModeSettings.java b/src/com/android/settings/notification/zen/ZenModeSettings.java
index 871974b07a4..c92099a6db4 100644
--- a/src/com/android/settings/notification/zen/ZenModeSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSettings.java
@@ -25,15 +25,19 @@ import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
+import android.app.Activity;
+import android.app.Application;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.icu.text.ListFormatter;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
@@ -67,7 +71,9 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
protected List createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager());
+ final Activity activity = getActivity();
+ return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager(),
+ activity != null ? activity.getApplication() : null, this);
}
@Override
@@ -76,15 +82,19 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
private static List buildPreferenceControllers(Context context,
- Lifecycle lifecycle, FragmentManager fragmentManager) {
+ Lifecycle lifecycle, FragmentManager fragmentManager, Application app,
+ Fragment fragment) {
List controllers = new ArrayList<>();
+ controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModePeoplePreferenceController(context, lifecycle,
"zen_mode_behavior_people"));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBypassingAppsPreferenceController(context, app,
+ fragment, lifecycle));
+ controllers.add(new ZenModeSoundVibrationPreferenceController(context, lifecycle,
+ "zen_sound_vibration_settings"));
controllers.add(new ZenModeAutomationPreferenceController(context));
- controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
+ controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
fragmentManager));
return controllers;
@@ -110,29 +120,34 @@ public class ZenModeSettings extends ZenModeSettingsBase {
PRIORITY_CATEGORY_REPEAT_CALLERS,
};
- String getSoundSettingSummary(Policy policy) {
- List enabledCategories = getEnabledCategories(policy,
+ String getOtherSoundCategoriesSummary(Policy policy) {
+ List enabledCategories = getEnabledCategories(
+ policy,
category -> PRIORITY_CATEGORY_ALARMS == category
|| PRIORITY_CATEGORY_MEDIA == category
- || PRIORITY_CATEGORY_SYSTEM == category, false);
+ || PRIORITY_CATEGORY_SYSTEM == category
+ || PRIORITY_CATEGORY_REMINDERS == category
+ || PRIORITY_CATEGORY_EVENTS == category,
+ true);
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_sound_all_muted);
- } else if (numCategories == 1) {
- return mContext.getString(R.string.zen_sound_one_allowed,
- enabledCategories.get(0));
- } else if (numCategories == 2) {
- return mContext.getString(R.string.zen_sound_two_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1));
- } else if (numCategories == 3) {
- return mContext.getString(R.string.zen_sound_three_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1),
- enabledCategories.get(2));
- } else {
- return mContext.getString(R.string.zen_sound_none_muted);
+ return mContext.getResources().getString(R.string.zen_mode_other_sounds_none);
}
+
+ List displayCategories = new ArrayList<>();
+ if (numCategories <= 2) {
+ displayCategories = enabledCategories;
+ } else {
+ displayCategories.add(enabledCategories.get(0));
+ displayCategories.add(enabledCategories.get(1));
+ displayCategories.add(mContext.getString(R.string.zen_mode_other_sounds_list_count,
+ numCategories - 2));
+ }
+
+ return mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_other_sounds_summary,
+ numCategories /* quantity */,
+ ListFormatter.getInstance().format(displayCategories));
}
String getCallsSettingSummary(Policy policy) {
@@ -322,7 +337,8 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public List createPreferenceControllers(Context
context) {
- return buildPreferenceControllers(context, null, null);
+ return buildPreferenceControllers(context, null, null,
+ null, null);
}
};
}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
new file mode 100644
index 00000000000..691c2aede69
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 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.zen;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Alarms & other interruptions
+ */
+public class ZenModeSoundVibrationPreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+ private final String mKey;
+ private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public ZenModeSoundVibrationPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ mKey = key;
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return mKey;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_other_sounds_none));
+ break;
+ case Settings.Global.ZEN_MODE_ALARMS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_behavior_alarms_only));
+ break;
+ default:
+ preference.setEnabled(true);
+ preference.setSummary(mSummaryBuilder.getOtherSoundCategoriesSummary(getPolicy()));
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
index 3d4f3c2206f..c07ee773c85 100644
--- a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
@@ -21,14 +21,17 @@ import android.content.Context;
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Settings > Sound > Do Not Disturb > Alarms & Other Interruptions
+ */
@SearchIndexable
public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implements Indexable {
@@ -40,10 +43,6 @@ public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implement
private static List buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List controllers = new ArrayList<>();
- controllers.add(new ZenModeCallsPreferenceController(context, lifecycle,
- "zen_mode_calls_settings"));
- controllers.add(new ZenModeMessagesPreferenceController(context, lifecycle,
- "zen_mode_messages_settings"));
controllers.add(new ZenModeAlarmsPreferenceController(context, lifecycle,
"zen_mode_alarms"));
controllers.add(new ZenModeMediaPreferenceController(context, lifecycle));
@@ -52,7 +51,6 @@ public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implement
controllers.add(new ZenModeEventsPreferenceController(context, lifecycle));
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle,
R.string.zen_sound_footer));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
return controllers;
}
diff --git a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java
index f5af290dcc2..15d4c973baf 100644
--- a/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/display/BrightnessLevelPreferenceControllerTest.java
@@ -67,10 +67,14 @@ public class BrightnessLevelPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mContentResolver = mContext.getContentResolver();
- when(mPowerManager.getMinimumScreenBrightnessSetting()).thenReturn(0);
- when(mPowerManager.getMaximumScreenBrightnessSetting()).thenReturn(100);
- when(mPowerManager.getMinimumScreenBrightnessForVrSetting()).thenReturn(0);
- when(mPowerManager.getMaximumScreenBrightnessForVrSetting()).thenReturn(100);
+ when(mPowerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM)).thenReturn(0.0f);
+ when(mPowerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM)).thenReturn(1.0f);
+ when(mPowerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MINIMUM_VR)).thenReturn(0.0f);
+ when(mPowerManager.getBrightnessConstraint(
+ PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_MAXIMUM_VR)).thenReturn(1.0f);
ShadowApplication.getInstance().setSystemService(POWER_SERVICE,
mPowerManager);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
@@ -98,7 +102,7 @@ public class BrightnessLevelPreferenceControllerTest {
controller.onStart();
assertThat(shadowContentResolver.getContentObservers(
- System.getUriFor(System.SCREEN_BRIGHTNESS))).isNotEmpty();
+ System.getUriFor(System.SCREEN_BRIGHTNESS_FLOAT))).isNotEmpty();
assertThat(shadowContentResolver.getContentObservers(
System.getUriFor(System.SCREEN_BRIGHTNESS_FOR_VR))).isNotEmpty();
assertThat(shadowContentResolver.getContentObservers(
@@ -116,9 +120,9 @@ public class BrightnessLevelPreferenceControllerTest {
controller.onStop();
assertThat(shadowContentResolver.getContentObservers(
- System.getUriFor(System.SCREEN_BRIGHTNESS))).isEmpty();
+ System.getUriFor(System.SCREEN_BRIGHTNESS_FLOAT))).isEmpty();
assertThat(shadowContentResolver.getContentObservers(
- System.getUriFor(System.SCREEN_BRIGHTNESS_FOR_VR))).isEmpty();
+ System.getUriFor(System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT))).isEmpty();
assertThat(shadowContentResolver.getContentObservers(
System.getUriFor(System.SCREEN_AUTO_BRIGHTNESS_ADJ))).isEmpty();
}
@@ -126,11 +130,11 @@ public class BrightnessLevelPreferenceControllerTest {
@Test
public void updateState_inVrMode_shouldSetSummaryToVrBrightness() {
doReturn(true).when(mController).isInVrMode();
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR, 85);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, 0.6f);
mController.updateState(mPreference);
- verify(mPreference).setSummary("97%");
+ verify(mPreference).setSummary("91%");
}
@Test
@@ -139,11 +143,11 @@ public class BrightnessLevelPreferenceControllerTest {
System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS_MODE,
System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, 31);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, 0.1f);
mController.updateState(mPreference);
- verify(mPreference).setSummary("78%");
+ verify(mPreference).setSummary("54%");
}
@Test
@@ -152,11 +156,11 @@ public class BrightnessLevelPreferenceControllerTest {
System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS_MODE,
System.SCREEN_BRIGHTNESS_MODE_MANUAL);
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, 45);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, 0.5f);
mController.updateState(mPreference);
- verify(mPreference).setSummary("85%");
+ verify(mPreference).setSummary("87%");
}
@Test
@@ -164,11 +168,11 @@ public class BrightnessLevelPreferenceControllerTest {
// VR mode
doReturn(true).when(mController).isInVrMode();
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR, 105);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, 1.05f);
mController.updateState(mPreference);
verify(mPreference).setSummary("100%");
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR, -20);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FOR_VR_FLOAT, -20f);
mController.updateState(mPreference);
verify(mPreference).setSummary("0%");
@@ -178,11 +182,11 @@ public class BrightnessLevelPreferenceControllerTest {
System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
reset(mPreference);
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, 115);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, 1.15f);
mController.updateState(mPreference);
verify(mPreference).setSummary("100%");
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, -10);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, -10f);
mController.updateState(mPreference);
verify(mPreference).setSummary("0%");
@@ -191,11 +195,11 @@ public class BrightnessLevelPreferenceControllerTest {
System.SCREEN_BRIGHTNESS_MODE_MANUAL);
reset(mPreference);
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, 115);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, 1.15f);
mController.updateState(mPreference);
verify(mPreference).setSummary("100%");
- System.putInt(mContentResolver, System.SCREEN_BRIGHTNESS, -10);
+ System.putFloat(mContentResolver, System.SCREEN_BRIGHTNESS_FLOAT, -10f);
mController.updateState(mPreference);
verify(mPreference).setSummary("0%");
}
diff --git a/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java b/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java
index 97d76ca7beb..515ab5b659b 100644
--- a/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java
+++ b/tests/robotests/src/com/android/settings/network/ims/MockVolteQueryImsState.java
@@ -19,10 +19,6 @@ package com.android.settings.network.ims;
import android.content.Context;
import android.telephony.ims.ImsException;
-import com.android.ims.ImsManager;
-
-
-
/**
* Controller class for mock VoLte status
*/
@@ -31,6 +27,7 @@ public class MockVolteQueryImsState extends VolteQueryImsState {
private Boolean mIsTtyOnVolteEnabled;
private Boolean mIsSupported;
private Boolean mIsProvisionedOnDevice;
+ private Boolean mIsServiceStateReady;
private Boolean mIsEnabledByUser;
/**
@@ -43,10 +40,6 @@ public class MockVolteQueryImsState extends VolteQueryImsState {
super(context, subId);
}
- public ImsManager getImsManager(int subId) {
- return super.getImsManager(subId);
- }
-
public void setIsTtyOnVolteEnabled(boolean enabled) {
mIsTtyOnVolteEnabled = enabled;
}
@@ -84,6 +77,19 @@ public class MockVolteQueryImsState extends VolteQueryImsState {
return super.isProvisionedOnDevice(subId);
}
+ public void setServiceStateReady(boolean isReady) {
+ mIsServiceStateReady = isReady;
+ }
+
+ @Override
+ boolean isServiceStateReady(int subId) throws InterruptedException, ImsException,
+ IllegalArgumentException {
+ if (mIsServiceStateReady != null) {
+ return mIsServiceStateReady;
+ }
+ return super.isServiceStateReady(subId);
+ }
+
public void setIsEnabledByUser(boolean enabled) {
mIsEnabledByUser = enabled;
}
diff --git a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceControllerTest.java
index ba71a7952fe..598f30ae06d 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gBasePreferenceControllerTest.java
@@ -28,12 +28,9 @@ import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ProvisioningManager;
-import android.telephony.ims.feature.MmTelFeature;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
import androidx.preference.SwitchPreference;
-import com.android.ims.ImsManager;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.ims.MockVolteQueryImsState;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -59,8 +56,6 @@ public class Enhanced4gBasePreferenceControllerTest {
@Mock
private CarrierConfigManager mCarrierConfigManager;
@Mock
- private ImsManager mImsManager;
- @Mock
private ProvisioningManager mProvisioningManager;
private MockVolteQueryImsState mQueryImsState;
@@ -86,9 +81,10 @@ public class Enhanced4gBasePreferenceControllerTest {
doReturn(mCarrierConfig).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
mQueryImsState = spy(new MockVolteQueryImsState(mContext, SUB_ID));
- doReturn(mImsManager).when(mQueryImsState).getImsManager(anyInt());
mQueryImsState.setEnabledByPlatform(true);
mQueryImsState.setIsProvisionedOnDevice(true);
+ mQueryImsState.setIsTtyOnVolteEnabled(true);
+ mQueryImsState.setServiceStateReady(true);
mQueryImsState.setIsEnabledByUser(true);
mPreference = new RestrictedSwitchPreference(mContext);
@@ -100,6 +96,9 @@ public class Enhanced4gBasePreferenceControllerTest {
@Test
public void getAvailabilityStatus_default_returnUnavailable() {
+ mQueryImsState.setEnabledByPlatform(false);
+ mQueryImsState.setIsProvisionedOnDevice(false);
+
mController.init(SUB_ID);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
@@ -109,9 +108,6 @@ public class Enhanced4gBasePreferenceControllerTest {
@Test
public void getAvailabilityStatus_volteDisabled_returnUnavailable() {
mQueryImsState.setEnabledByPlatform(false);
- doReturn(true).when(mProvisioningManager).getProvisioningStatusForCapability(
- MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
@@ -123,7 +119,6 @@ public class Enhanced4gBasePreferenceControllerTest {
mPreference.setEnabled(false);
mCarrierConfig.putInt(CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_INT, 1);
mController.mCallState = TelephonyManager.CALL_STATE_IDLE;
- doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
mCarrierConfig.putBoolean(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL, true);
mController.updateState(mPreference);
@@ -135,8 +130,6 @@ public class Enhanced4gBasePreferenceControllerTest {
public void updateState_configOn_prefChecked() {
mQueryImsState.setIsEnabledByUser(true);
mPreference.setChecked(false);
- doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
- doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
index 944d8e623b2..50446ad2f14 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/Enhanced4gLteSliceHelperTest.java
@@ -43,7 +43,6 @@ import androidx.slice.core.SliceAction;
import androidx.slice.core.SliceQuery;
import androidx.slice.widget.SliceLiveData;
-import com.android.ims.ImsManager;
import com.android.settings.R;
import com.android.settings.network.ims.MockVolteQueryImsState;
import com.android.settings.slices.CustomSliceRegistry;
@@ -73,8 +72,6 @@ public class Enhanced4gLteSliceHelperTest {
@Mock
private CarrierConfigManager mMockCarrierConfigManager;
- @Mock
- private ImsManager mMockImsManager;
@Mock
private ProvisioningManager mProvisioningManager;
@@ -109,9 +106,10 @@ public class Enhanced4gLteSliceHelperTest {
mReceiver = spy(new SliceBroadcastReceiver());
mQueryImsState = spy(new MockVolteQueryImsState(mContext, SUB_ID));
- doReturn(mMockImsManager).when(mQueryImsState).getImsManager(anyInt());
mQueryImsState.setEnabledByPlatform(true);
mQueryImsState.setIsProvisionedOnDevice(true);
+ mQueryImsState.setIsTtyOnVolteEnabled(true);
+ mQueryImsState.setServiceStateReady(true);
mQueryImsState.setIsEnabledByUser(true);
mEnhanced4gLteSliceHelper = spy(new FakeEnhanced4gLteSliceHelper(mContext));
@@ -149,7 +147,6 @@ public class Enhanced4gLteSliceHelperTest {
public void test_CreateEnhanced4gLteSlice_success() {
mQueryImsState.setEnabledByPlatform(true);
mQueryImsState.setIsProvisionedOnDevice(true);
- when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
final Slice slice = mEnhanced4gLteSliceHelper.createEnhanced4gLteSlice(
@@ -163,7 +160,6 @@ public class Enhanced4gLteSliceHelperTest {
public void test_SettingSliceProvider_getsRightSliceEnhanced4gLte() {
mQueryImsState.setEnabledByPlatform(true);
mQueryImsState.setIsProvisionedOnDevice(true);
- when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
when(mMockCarrierConfigManager.getConfigForSubId(1)).thenReturn(null);
when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext))
.thenReturn(mEnhanced4gLteSliceHelper);
@@ -180,7 +176,6 @@ public class Enhanced4gLteSliceHelperTest {
mQueryImsState.setEnabledByPlatform(true);
mQueryImsState.setIsProvisionedOnDevice(true);
mQueryImsState.setIsEnabledByUser(false);
- when(mMockImsManager.isNonTtyOrTtyOnVolteEnabled()).thenReturn(true);
when(mSlicesFeatureProvider.getNewEnhanced4gLteSliceHelper(mContext))
.thenReturn(mEnhanced4gLteSliceHelper);
@@ -194,7 +189,7 @@ public class Enhanced4gLteSliceHelperTest {
// change the setting
mReceiver.onReceive(mContext, intent);
- verify((mMockImsManager)).setEnhanced4gLteModeSetting(
+ verify(mEnhanced4gLteSliceHelper).setEnhanced4gLteModeSetting(anyInt(),
mEnhanced4gLteSettingCaptor.capture());
// assert the change
diff --git a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
index 404625efde2..c2c45cb1707 100644
--- a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
@@ -122,7 +122,7 @@ public class BubblePreferenceControllerTest {
}
@Test
- public void testIsAvailable_channel_notIfAppOff() {
+ public void testIsAvailable_channel_yesIfAppOff() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.allowBubbles = false;
@@ -130,7 +130,7 @@ public class BubblePreferenceControllerTest {
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
- assertFalse(mController.isAvailable());
+ assertTrue(mController.isAvailable());
}
@Test
@@ -199,18 +199,6 @@ public class BubblePreferenceControllerTest {
assertTrue(mController.isAvailable());
}
- @Test
- public void testIsAvailable_channelAppOff() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = false;
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
-
- assertFalse(mController.isAvailable());
- }
-
@Test
public void testUpdateState_disabledByAdmin() {
NotificationChannel channel = mock(NotificationChannel.class);
diff --git a/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java
deleted file mode 100644
index 42b785976bd..00000000000
--- a/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2020 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.app;
-
-import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
-
-@RunWith(RobolectricTestRunner.class)
-public class ConversationImportantPreferenceControllerTest {
-
- private Context mContext;
- @Mock
- private NotificationBackend mBackend;
- @Mock
- private NotificationManager mNm;
- @Mock
- private UserManager mUm;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private PreferenceScreen mScreen;
- @Mock
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
-
- private ConversationImportantPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
- shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
- mContext = RuntimeEnvironment.application;
- mController = spy(new ConversationImportantPreferenceController(
- mContext, mBackend, mDependentFieldListener));
- }
-
- @Test
- public void testNoCrashIfNoOnResume() {
- mController.isAvailable();
- mController.updateState(mock(Preference.class));
- mController.onPreferenceChange(mock(Preference.class), true);
- }
-
- @Test
- public void testIsAvailable_notChannelNull() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- mController.onResume(appRow, null, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
- mController.onResume(appRow, channel, null, null, null, null);
- assertTrue(mController.isAvailable());
- }
-
- @Test
- public void testUpdateState_disabledByAdmin() {
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getId()).thenReturn("something");
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, mock(
- RestrictedLockUtils.EnforcedAdmin.class));
-
- Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- assertFalse(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(true);
- mController.onResume(appRow, channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- assertTrue(pref.isChecked());
-
- channel.setImportantConversation(false);
- mController.onResume(appRow, channel, null, null, null, null);
- mController.updateState(pref);
- assertFalse(pref.isChecked());
- }
-
- @Test
- public void testOnPreferenceChange_on() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 0);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(false);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, true);
-
- assertTrue(channel.isImportantConversation());
- assertFalse(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-
- @Test
- public void testOnPreferenceChange_on_bubble() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(false);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, true);
-
- assertTrue(channel.isImportantConversation());
- assertTrue(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener).onFieldValueChanged();
- }
-
- @Test
- public void testOnPreferenceChange_off() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
- channel.setImportantConversation(true);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, false);
-
- assertFalse(channel.isImportantConversation());
- assertFalse(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java
similarity index 58%
rename from tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java
index 5b853226c69..d74715c9da4 100644
--- a/tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2020 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.
@@ -20,28 +20,32 @@ import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.os.UserManager;
+import android.util.Pair;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Before;
import org.junit.Test;
@@ -54,21 +58,21 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
@RunWith(RobolectricTestRunner.class)
-public class DefaultImportancePreferenceControllerTest {
+public class ConversationPriorityPreferenceControllerTest {
private Context mContext;
@Mock
- private NotificationManager mNm;
- @Mock
private NotificationBackend mBackend;
@Mock
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
+ private NotificationManager mNm;
@Mock
private UserManager mUm;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
+ @Mock
+ private NotificationSettings.DependentFieldListener mDependentFieldListener;
- private DefaultImportancePreferenceController mController;
+ private ConversationPriorityPreferenceController mController;
@Before
public void setUp() {
@@ -77,54 +81,28 @@ public class DefaultImportancePreferenceControllerTest {
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
mContext = RuntimeEnvironment.application;
- mController = spy(new DefaultImportancePreferenceController(
- mContext, mDependentFieldListener, mBackend));
+ mController = spy(new ConversationPriorityPreferenceController(
+ mContext, mBackend, mDependentFieldListener));
}
@Test
public void testNoCrashIfNoOnResume() {
mController.isAvailable();
mController.updateState(mock(Preference.class));
+ mController.onPreferenceChange(mock(Preference.class), true);
}
@Test
- public void testIsAvailable_notIfNull() {
- mController.onResume(null, null, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_ifAppBlocked() {
+ public void testIsAvailable_notChannelNull() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.banned = true;
- mController.onResume(appRow, mock(NotificationChannel.class), null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_notIfChannelBlocked() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
- mController.onResume(appRow, channel, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_notForDefaultChannel() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
- mController.onResume(appRow, channel, null, null, null, null);
+ mController.onResume(appRow, null, null, null, null, null);
assertFalse(mController.isAvailable());
}
@Test
public void testIsAvailable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
mController.onResume(appRow, channel, null, null, null, null);
assertTrue(mController.isAvailable());
}
@@ -136,7 +114,7 @@ public class DefaultImportancePreferenceControllerTest {
mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, mock(
RestrictedLockUtils.EnforcedAdmin.class));
- Preference pref = new RestrictedSwitchPreference(mContext, null);
+ Preference pref = new ConversationPriorityPreference(mContext, null);
mController.updateState(pref);
assertFalse(pref.isEnabled());
@@ -150,7 +128,7 @@ public class DefaultImportancePreferenceControllerTest {
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
- Preference pref = new RestrictedSwitchPreference(mContext, null);
+ Preference pref = new ConversationPriorityPreference(mContext, null);
mController.updateState(pref);
assertFalse(pref.isEnabled());
@@ -165,7 +143,7 @@ public class DefaultImportancePreferenceControllerTest {
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
- Preference pref = new RestrictedSwitchPreference(mContext, null);
+ Preference pref = new ConversationPriorityPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
@@ -180,67 +158,120 @@ public class DefaultImportancePreferenceControllerTest {
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
- Preference pref = new RestrictedSwitchPreference(mContext, null);
+ Preference pref = new ConversationPriorityPreference(mContext, null);
mController.updateState(pref);
assertTrue(pref.isEnabled());
}
@Test
- public void testUpdateState_default() {
+ public void testUpdateState() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+ channel.setImportantConversation(true);
+ channel.setOriginalImportance(IMPORTANCE_DEFAULT);
mController.onResume(appRow, channel, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+ ConversationPriorityPreference pref = mock(ConversationPriorityPreference.class);
mController.updateState(pref);
- assertTrue(pref.isChecked());
+ verify(pref, times(1)).setConfigurable(anyBoolean());
+ verify(pref, times(1)).setImportance(IMPORTANCE_HIGH);
+ verify(pref, times(1)).setOriginalImportance(IMPORTANCE_DEFAULT);
+ verify(pref, times(1)).setPriorityConversation(true);
}
@Test
- public void testUpdateState_low() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
- mController.onResume(appRow, channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- mController.updateState(pref);
-
- assertFalse(pref.isChecked());
- }
-
- @Test
- public void onPreferenceChange_onToOff() {
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, false);
-
- assertEquals(IMPORTANCE_LOW, channel.getImportance());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-
- @Test
- public void onPreferenceChange_offToOn() {
+ public void testImportanceLowToImportant() {
NotificationChannel channel =
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
mController.displayPreference(mScreen);
mController.updateState(pref);
- mController.onPreferenceChange(pref, true);
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, true));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertTrue(channel.canBubble());
+ assertTrue(channel.isImportantConversation());
+ }
+ @Test
+ public void testImportanceLowToDefault() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+ channel.setAllowBubbles(false);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, false));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportanceDefaultToLow() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
+ channel.setAllowBubbles(false);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_LOW, false));
+
+ assertEquals(IMPORTANCE_LOW, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportanceLowToDefault_bubblesMaintained() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+ channel.setAllowBubbles(true);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_DEFAULT, false));
assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
+ assertTrue(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportancePriorityToDefault() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
+ channel.setAllowBubbles(true);
+ channel.setImportantConversation(true);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, false));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java
new file mode 100644
index 00000000000..12e1f35c767
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 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.app;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ConversationPriorityPreferenceTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void createNewPreference_shouldSetLayout() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ assertThat(preference.getLayoutResource()).isEqualTo(
+ R.layout.notif_priority_conversation_preference);
+ }
+
+ @Test
+ public void onBindViewHolder_nonConfigurable() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(false);
+ preference.setImportance(IMPORTANCE_DEFAULT);
+ preference.setPriorityConversation(true);
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.silence).isEnabled()).isFalse();
+ assertThat(holder.itemView.findViewById(R.id.priority_group).isEnabled()).isFalse();
+ assertThat(holder.itemView.findViewById(R.id.alert).isEnabled()).isFalse();
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(unselected);
+
+ // other button
+ preference.setPriorityConversation(false);
+ holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+
+ // other other button
+ preference.setImportance(IMPORTANCE_LOW);
+ holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground()).isEqualTo(selected);
+ }
+
+ @Test
+ public void onBindViewHolder_selectButtonAndText() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(true);
+ preference.setImportance(IMPORTANCE_LOW);
+ preference.setPriorityConversation(true);
+
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.silence_summary).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onClick_changesUICallsListener() {
+ final ConversationPriorityPreference preference =
+ spy(new ConversationPriorityPreference(mContext));
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(true);
+ preference.setImportance(IMPORTANCE_DEFAULT);
+ preference.setPriorityConversation(true);
+ preference.setOriginalImportance(IMPORTANCE_DEFAULT);
+ preference.onBindViewHolder(holder);
+
+ View silenceButton = holder.itemView.findViewById(R.id.silence);
+
+ silenceButton.callOnClick();
+
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(selected);
+
+ verify(preference, times(1)).callChangeListener(new Pair(IMPORTANCE_LOW, false));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
index 8760d4ce180..a6efaaf883c 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
@@ -18,16 +18,23 @@ package com.android.settings.notification.zen;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.NotificationChannel;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ParceledListSlice;
+import android.provider.Settings;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
import com.android.settings.notification.NotificationBackend;
-import com.android.settings.notification.zen.ZenModeBypassingAppsPreferenceController;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,6 +44,9 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ZenModeBypassingAppsPreferenceControllerTest {
@@ -45,30 +55,156 @@ public class ZenModeBypassingAppsPreferenceControllerTest {
private Context mContext;
@Mock
private NotificationBackend mBackend;
+ private int mPreviousZenSetting;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
-
- mController = new ZenModeBypassingAppsPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeBypassingAppsPreferenceController(
+ mContext, null, mock(Fragment.class), mock(Lifecycle.class));
+ mController.mPreference = new Preference(mContext);
+ mPreviousZenSetting =
+ Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
ReflectionHelpers.setField(mController, "mNotificationBackend", mBackend);
}
+ @After
+ public void tearDown() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ mPreviousZenSetting);
+ }
+
@Test
public void testIsAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(5);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void testNotAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(0);
- assertThat(mController.isAvailable()).isFalse();
+ public void testUpdateBypassingApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a single app is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app name from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry.label)).isTrue();
}
@Test
- public void testHasSummary() {
- assertThat(mController.getSummary()).isNotNull();
+ public void testUpdateBypassingApps_multipleApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry1 = mock(ApplicationsState.AppEntry.class);
+ entry1.info = new ApplicationInfo();
+ entry1.info.packageName = "test1";
+ entry1.label = "test1";
+ entry1.info.uid = 1;
+ ApplicationsState.AppEntry entry2 = mock(ApplicationsState.AppEntry.class);
+ entry2.info = new ApplicationInfo();
+ entry2.info.packageName = "test2";
+ entry2.label = "test2";
+ entry2.info.uid = 2;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry1);
+ appEntries.add(entry2);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry1.info.packageName,
+ entry1.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry2.info.packageName,
+ entry2.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a list of apps is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app names from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry1.label)).isTrue();
+ assertThat(mController.getSummary().contains(entry2.label)).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_nullAppsList() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is null
+ mController.updateAppsBypassingDndSummaryText(null);
+
+ // THEN the preference is enabled and summary is unchanged (in this case, null)
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary()).isNull();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_emptyAppsList() {
+ // GIVEN the DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is an empty list
+ mController.updateAppsBypassingDndSummaryText(new ArrayList<>());
+
+ // THEN the preference is enabled and summary is updated
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_alarmsOnly() {
+ // GIVEN alarms only DND mode
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_ALARMS);
+
+ // mock app entries
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN we update apps bypassing dnd summary text
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is disabled and the summary says no apps can bypass
+ assertThat(mController.mPreference.isEnabled()).isFalse();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
index da185adedb0..d3c3a85a5ad 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
@@ -97,34 +97,6 @@ public class ZenModeSettingsTest {
.isEqualTo("Allow from starred contacts and repeat callers");
}
- @Test
- public void testGetSoundSettingSummary_allOff() {
- Policy policy = new Policy(0, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOn() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow alarms, media, and touch sounds");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButOne() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted, but allow media");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButTwo() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow media and touch sounds");
- }
-
@Test
public void searchProvider_shouldIndexDefaultXml() {
final List sir = ZenModeSettings.SEARCH_INDEX_DATA_PROVIDER