Expand the visual effects that DND can suppress.

am: ccc6ae64ff

Change-Id: I216d9ffcbe4fe1876ba9e40063714aeae1f3add3
This commit is contained in:
Julia Reynolds
2018-03-09 15:10:14 +00:00
committed by android-build-merger
17 changed files with 709 additions and 59 deletions

View File

@@ -5752,8 +5752,15 @@ package android.app {
field public static final int PRIORITY_SENDERS_ANY = 0; // 0x0
field public static final int PRIORITY_SENDERS_CONTACTS = 1; // 0x1
field public static final int PRIORITY_SENDERS_STARRED = 2; // 0x2
field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
field public static final int SUPPRESSED_EFFECT_AMBIENT = 128; // 0x80
field public static final int SUPPRESSED_EFFECT_BADGE = 64; // 0x40
field public static final int SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 4; // 0x4
field public static final int SUPPRESSED_EFFECT_LIGHTS = 8; // 0x8
field public static final int SUPPRESSED_EFFECT_NOTIFICATION_LIST = 256; // 0x100
field public static final int SUPPRESSED_EFFECT_PEEK = 16; // 0x10
field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
field public static final int SUPPRESSED_EFFECT_STATUS_BAR = 32; // 0x20
field public final int priorityCallSenders;
field public final int priorityCategories;
field public final int priorityMessageSenders;
@@ -40001,8 +40008,8 @@ package android.service.notification {
field public static final int REASON_UNAUTOBUNDLED = 16; // 0x10
field public static final int REASON_USER_STOPPED = 6; // 0x6
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
field public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
field public static final int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_OFF = 1; // 0x1
field public static final deprecated int SUPPRESSED_EFFECT_SCREEN_ON = 2; // 0x2
}
public static class NotificationListenerService.Ranking {

View File

@@ -1072,20 +1072,77 @@ public class NotificationManager {
* @hide
*/
public static final int SUPPRESSED_EFFECTS_UNSET = -1;
/**
* Whether notifications suppressed by DND should not interrupt visually (e.g. with
* notification lights or by turning the screen on) when the screen is off.
*
* @deprecated use {@link #SUPPRESSED_EFFECT_FULL_SCREEN_INTENT} and
* {@link #SUPPRESSED_EFFECT_AMBIENT} and {@link #SUPPRESSED_EFFECT_LIGHTS} individually.
*/
@Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_OFF = 1 << 0;
/**
* Whether notifications suppressed by DND should not interrupt visually when the screen
* is on (e.g. by peeking onto the screen).
*
* @deprecated use {@link #SUPPRESSED_EFFECT_PEEK}.
*/
@Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_ON = 1 << 1;
/**
* Whether {@link Notification#fullScreenIntent full screen intents} from
* notifications intercepted by DND are blocked.
*/
public static final int SUPPRESSED_EFFECT_FULL_SCREEN_INTENT = 1 << 2;
/**
* Whether {@link NotificationChannel#shouldShowLights() notification lights} from
* notifications intercepted by DND are blocked.
*/
public static final int SUPPRESSED_EFFECT_LIGHTS = 1 << 3;
/**
* Whether notifications intercepted by DND are prevented from peeking.
*/
public static final int SUPPRESSED_EFFECT_PEEK = 1 << 4;
/**
* Whether notifications intercepted by DND are prevented from appearing in the status bar,
* on devices that support status bars.
*/
public static final int SUPPRESSED_EFFECT_STATUS_BAR = 1 << 5;
/**
* Whether {@link NotificationChannel#canShowBadge() badges} from
* notifications intercepted by DND are blocked on devices that support badging.
*/
public static final int SUPPRESSED_EFFECT_BADGE = 1 << 6;
/**
* Whether notification intercepted by DND are prevented from appearing on ambient displays
* on devices that support ambient display.
*/
public static final int SUPPRESSED_EFFECT_AMBIENT = 1 << 7;
/**
* Whether notification intercepted by DND are prevented from appearing in notification
* list views like the notification shade or lockscreen on devices that support those
* views.
*/
public static final int SUPPRESSED_EFFECT_NOTIFICATION_LIST = 1 << 8;
private static final int[] ALL_SUPPRESSED_EFFECTS = {
SUPPRESSED_EFFECT_SCREEN_OFF,
SUPPRESSED_EFFECT_SCREEN_ON,
SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
SUPPRESSED_EFFECT_LIGHTS,
SUPPRESSED_EFFECT_PEEK,
SUPPRESSED_EFFECT_STATUS_BAR,
SUPPRESSED_EFFECT_BADGE,
SUPPRESSED_EFFECT_AMBIENT,
SUPPRESSED_EFFECT_NOTIFICATION_LIST
};
/**
@@ -1097,6 +1154,12 @@ public class NotificationManager {
/**
* Constructs a policy for Do Not Disturb priority mode behavior.
*
* <p>
* Apps that target API levels below {@link Build.VERSION_CODES#P} cannot
* change user-designated values to allow or disallow
* {@link Policy#PRIORITY_CATEGORY_ALARMS}, {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and
* {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd.
*
* @param priorityCategories bitmask of categories of notifications that can bypass DND.
* @param priorityCallSenders which callers can bypass DND.
* @param priorityMessageSenders which message senders can bypass DND.
@@ -1109,6 +1172,26 @@ public class NotificationManager {
/**
* Constructs a policy for Do Not Disturb priority mode behavior.
*
* <p>
* Apps that target API levels below {@link Build.VERSION_CODES#P} cannot
* change user-designated values to allow or disallow
* {@link Policy#PRIORITY_CATEGORY_ALARMS}, {@link Policy#PRIORITY_CATEGORY_SYSTEM}, and
* {@link Policy#PRIORITY_CATEGORY_MEDIA} from bypassing dnd.
* <p>
* Additionally, apps that target API levels below {@link Build.VERSION_CODES#P} can
* only modify the {@link #SUPPRESSED_EFFECT_SCREEN_ON} and
* {@link #SUPPRESSED_EFFECT_SCREEN_OFF} bits of the suppressed visual effects field.
* All other suppressed effects will be ignored and reconstituted from the screen on
* and screen off values.
* <p>
* Apps that target {@link Build.VERSION_CODES#P} or above can set any
* suppressed visual effects. However, if any suppressed effects >
* {@link #SUPPRESSED_EFFECT_SCREEN_ON} are set, {@link #SUPPRESSED_EFFECT_SCREEN_ON}
* and {@link #SUPPRESSED_EFFECT_SCREEN_OFF} will be ignored and reconstituted from
* the more specific suppressed visual effect bits. Apps should migrate to targeting
* specific effects instead of the deprecated {@link #SUPPRESSED_EFFECT_SCREEN_ON} and
* {@link #SUPPRESSED_EFFECT_SCREEN_OFF} effects.
*
* @param priorityCategories bitmask of categories of notifications that can bypass DND.
* @param priorityCallSenders which callers can bypass DND.
* @param priorityMessageSenders which message senders can bypass DND.
@@ -1190,6 +1273,30 @@ public class NotificationManager {
}
}
/**
* @hide
*/
public static int getAllSuppressedVisualEffects() {
int effects = 0;
for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
effects |= ALL_SUPPRESSED_EFFECTS[i];
}
return effects;
}
/**
* @hide
*/
public static boolean areAllVisualEffectsSuppressed(int effects) {
for (int i = 0; i < ALL_SUPPRESSED_EFFECTS.length; i++) {
final int effect = ALL_SUPPRESSED_EFFECTS[i];
if ((effects & effect) == 0) {
return false;
}
}
return true;
}
public static String suppressedEffectsToString(int effects) {
if (effects <= 0) return "";
final StringBuilder sb = new StringBuilder();
@@ -1228,9 +1335,26 @@ public class NotificationManager {
private static String effectToString(int effect) {
switch (effect) {
case SUPPRESSED_EFFECT_SCREEN_OFF: return "SUPPRESSED_EFFECT_SCREEN_OFF";
case SUPPRESSED_EFFECT_SCREEN_ON: return "SUPPRESSED_EFFECT_SCREEN_ON";
case SUPPRESSED_EFFECTS_UNSET: return "SUPPRESSED_EFFECTS_UNSET";
case SUPPRESSED_EFFECT_FULL_SCREEN_INTENT:
return "SUPPRESSED_EFFECT_FULL_SCREEN_INTENT";
case SUPPRESSED_EFFECT_LIGHTS:
return "SUPPRESSED_EFFECT_LIGHTS";
case SUPPRESSED_EFFECT_PEEK:
return "SUPPRESSED_EFFECT_PEEK";
case SUPPRESSED_EFFECT_STATUS_BAR:
return "SUPPRESSED_EFFECT_STATUS_BAR";
case SUPPRESSED_EFFECT_BADGE:
return "SUPPRESSED_EFFECT_BADGE";
case SUPPRESSED_EFFECT_AMBIENT:
return "SUPPRESSED_EFFECT_AMBIENT";
case SUPPRESSED_EFFECT_NOTIFICATION_LIST:
return "SUPPRESSED_EFFECT_NOTIFICATION_LIST";
case SUPPRESSED_EFFECT_SCREEN_OFF:
return "SUPPRESSED_EFFECT_SCREEN_OFF";
case SUPPRESSED_EFFECT_SCREEN_ON:
return "SUPPRESSED_EFFECT_SCREEN_ON";
case SUPPRESSED_EFFECTS_UNSET:
return "SUPPRESSED_EFFECTS_UNSET";
default: return "UNKNOWN_" + effect;
}
}

View File

@@ -149,13 +149,19 @@ public abstract class NotificationListenerService extends Service {
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* off.
*
* @deprecated Use the more specific visual effects in {@link NotificationManager.Policy}.
*/
@Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_OFF =
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* on.
*
* @deprecated Use the more specific visual effects in {@link NotificationManager.Policy}.
*/
@Deprecated
public static final int SUPPRESSED_EFFECT_SCREEN_ON =
NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
@@ -1453,7 +1459,8 @@ public abstract class NotificationListenerService extends Service {
/**
* Returns the type(s) of visual effects that should be suppressed for this notification.
* See {@link #SUPPRESSED_EFFECT_SCREEN_OFF}, {@link #SUPPRESSED_EFFECT_SCREEN_ON}.
* See {@link NotificationManager.Policy}, e.g.
* {@link NotificationManager.Policy#SUPPRESSED_EFFECT_LIGHTS}.
*/
public int getSuppressedVisualEffects() {
return mSuppressedVisualEffects;

View File

@@ -92,10 +92,12 @@ public class ZenModeConfig implements Parcelable {
private static final boolean DEFAULT_ALLOW_REMINDERS = false;
private static final boolean DEFAULT_ALLOW_EVENTS = false;
private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false;
private static final boolean DEFAULT_ALLOW_SCREEN_OFF = true;
private static final boolean DEFAULT_ALLOW_SCREEN_ON = true;
private static final boolean DEFAULT_ALLOW_SCREEN_OFF = false;
private static final boolean DEFAULT_ALLOW_SCREEN_ON = false;
private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS =
Policy.getAllSuppressedVisualEffects();
public static final int XML_VERSION = 4;
public static final int XML_VERSION = 5;
public static final String ZEN_TAG = "zen";
private static final String ZEN_ATT_VERSION = "version";
private static final String ZEN_ATT_USER = "user";
@@ -113,6 +115,8 @@ public class ZenModeConfig implements Parcelable {
private static final String ALLOW_ATT_EVENTS = "events";
private static final String ALLOW_ATT_SCREEN_OFF = "visualScreenOff";
private static final String ALLOW_ATT_SCREEN_ON = "visualScreenOn";
private static final String DISALLOW_TAG = "disallow";
private static final String DISALLOW_ATT_VISUAL_EFFECTS = "visualEffects";
private static final String CONDITION_ATT_ID = "id";
private static final String CONDITION_ATT_SUMMARY = "summary";
@@ -146,6 +150,7 @@ public class ZenModeConfig implements Parcelable {
public int allowCallsFrom = DEFAULT_SOURCE;
public int allowMessagesFrom = DEFAULT_SOURCE;
public int user = UserHandle.USER_SYSTEM;
public int suppressedVisualEffects = DEFAULT_SUPPRESSED_VISUAL_EFFECTS;
public boolean allowWhenScreenOff = DEFAULT_ALLOW_SCREEN_OFF;
public boolean allowWhenScreenOn = DEFAULT_ALLOW_SCREEN_ON;
public int version;
@@ -180,6 +185,7 @@ public class ZenModeConfig implements Parcelable {
allowAlarms = source.readInt() == 1;
allowMedia = source.readInt() == 1;
allowSystem = source.readInt() == 1;
suppressedVisualEffects = source.readInt();
}
@Override
@@ -212,6 +218,7 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(allowAlarms ? 1 : 0);
dest.writeInt(allowMedia ? 1 : 0);
dest.writeInt(allowSystem ? 1 : 0);
dest.writeInt(suppressedVisualEffects);
}
@Override
@@ -230,6 +237,7 @@ public class ZenModeConfig implements Parcelable {
.append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
.append(",allowWhenScreenOff=").append(allowWhenScreenOff)
.append(",allowWhenScreenOn=").append(allowWhenScreenOn)
.append(",suppressedVisualEffects=").append(suppressedVisualEffects)
.append(",automaticRules=").append(automaticRules)
.append(",manualRule=").append(manualRule)
.append(']').toString();
@@ -279,6 +287,10 @@ public class ZenModeConfig implements Parcelable {
if (allowWhenScreenOn != to.allowWhenScreenOn) {
d.addLine("allowWhenScreenOn", allowWhenScreenOn, to.allowWhenScreenOn);
}
if (suppressedVisualEffects != to.suppressedVisualEffects) {
d.addLine("suppressedVisualEffects", suppressedVisualEffects,
to.suppressedVisualEffects);
}
final ArraySet<String> allRules = new ArraySet<>();
addKeys(allRules, automaticRules);
addKeys(allRules, to.automaticRules);
@@ -383,7 +395,8 @@ public class ZenModeConfig implements Parcelable {
&& other.allowWhenScreenOn == allowWhenScreenOn
&& other.user == user
&& Objects.equals(other.automaticRules, automaticRules)
&& Objects.equals(other.manualRule, manualRule);
&& Objects.equals(other.manualRule, manualRule)
&& other.suppressedVisualEffects == suppressedVisualEffects;
}
@Override
@@ -391,7 +404,8 @@ public class ZenModeConfig implements Parcelable {
return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls,
allowRepeatCallers, allowMessages,
allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents,
allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule);
allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule,
suppressedVisualEffects);
}
private static String toDayList(int[] days) {
@@ -474,6 +488,8 @@ public class ZenModeConfig implements Parcelable {
rt.allowCallsFrom = DEFAULT_SOURCE;
rt.allowMessagesFrom = DEFAULT_SOURCE;
}
// continue to read even though we now have suppressedVisualEffects, in case
// we need to revert to users' previous settings
rt.allowWhenScreenOff =
safeBoolean(parser, ALLOW_ATT_SCREEN_OFF, DEFAULT_ALLOW_SCREEN_OFF);
rt.allowWhenScreenOn =
@@ -482,6 +498,9 @@ public class ZenModeConfig implements Parcelable {
rt.allowMedia = safeBoolean(parser, ALLOW_ATT_MEDIA,
DEFAULT_ALLOW_MEDIA);
rt.allowSystem = safeBoolean(parser, ALLOW_ATT_SYSTEM, DEFAULT_ALLOW_SYSTEM);
} else if (DISALLOW_TAG.equals(tag)) {
rt.suppressedVisualEffects = safeInt(parser, DISALLOW_ATT_VISUAL_EFFECTS,
DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
} else if (MANUAL_TAG.equals(tag)) {
rt.manualRule = readRuleXml(parser);
} else if (AUTOMATIC_TAG.equals(tag)) {
@@ -517,6 +536,10 @@ public class ZenModeConfig implements Parcelable {
out.attribute(null, ALLOW_ATT_SYSTEM, Boolean.toString(allowSystem));
out.endTag(null, ALLOW_TAG);
out.startTag(null, DISALLOW_TAG);
out.attribute(null, DISALLOW_ATT_VISUAL_EFFECTS, Integer.toString(suppressedVisualEffects));
out.endTag(null, DISALLOW_TAG);
if (manualRule != null) {
out.startTag(null, MANUAL_TAG);
writeRuleXml(manualRule, out);
@@ -701,13 +724,6 @@ public class ZenModeConfig implements Parcelable {
if (allowRepeatCallers) {
priorityCategories |= Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
}
int suppressedVisualEffects = 0;
if (!allowWhenScreenOff) {
suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
}
if (!allowWhenScreenOn) {
suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_SCREEN_ON;
}
if (allowAlarms) {
priorityCategories |= Policy.PRIORITY_CATEGORY_ALARMS;
}
@@ -770,10 +786,7 @@ public class ZenModeConfig implements Parcelable {
allowMessagesFrom = prioritySendersToSource(policy.priorityMessageSenders,
allowMessagesFrom);
if (policy.suppressedVisualEffects != Policy.SUPPRESSED_EFFECTS_UNSET) {
allowWhenScreenOff =
(policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_SCREEN_OFF) == 0;
allowWhenScreenOn =
(policy.suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_SCREEN_ON) == 0;
suppressedVisualEffects = policy.suppressedVisualEffects;
}
}

View File

@@ -2396,6 +2396,7 @@
<!-- depends on ImportanceExtractor-->
<item>com.android.server.notification.NotificationIntrusivenessExtractor</item>
<item>com.android.server.notification.VisibilityExtractor</item>
<!-- Depends on ZenModeExtractor -->
<item>com.android.server.notification.BadgeExtractor</item>
</string-array>

View File

@@ -4883,7 +4883,7 @@
<!-- Title for the notification channel notifying user of settings system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] -->
<string name="notification_channel_system_changes">System changes</string>
<!-- Title of notification indicating do not disturb settings have changed when upgrading to P -->
<string name="zen_upgrade_notification_title">Do Not Disturb has changed</string>
<string name="zen_upgrade_notification_title">Do Not Disturb is hiding notifications to help you focus</string>
<!-- Content of notification indicating users can tap on the notification to go to dnd behavior settings -->
<string name="zen_upgrade_notification_content">Tap to check your behavior settings for interruptions</string>
<string name="zen_upgrade_notification_content">This is a new feature from the latest system update. Tap to change.</string>
</resources>

View File

@@ -18,7 +18,9 @@
-->
<!-- Default configuration for zen mode. See android.service.notification.ZenModeConfig. -->
<zen version="4">
<zen version="5">
<allow alarms="true" media="true" system="false" calls="false" messages="false" reminders="false"
events="false" />
<!-- all visual effects that exist as of P -->
<disallow suppressedVisualEffect="511" />
</zen>

View File

@@ -15,6 +15,8 @@
*/
package com.android.server.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import android.content.Context;
import android.util.Slog;
@@ -54,6 +56,11 @@ public class BadgeExtractor implements NotificationSignalExtractor {
}
}
if (record.isIntercepted()
&& (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_BADGE) != 0) {
record.setShowBadge(false);
}
return null;
}
@@ -64,6 +71,5 @@ public class BadgeExtractor implements NotificationSignalExtractor {
@Override
public void setZenHelper(ZenModeHelper helper) {
}
}

View File

@@ -22,6 +22,16 @@ import static android.app.NotificationManager.ACTION_NOTIFICATION_CHANNEL_GROUP_
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECTS_UNSET;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -60,8 +70,6 @@ import static android.service.notification.NotificationListenerService.REASON_SN
import static android.service.notification.NotificationListenerService.REASON_TIMEOUT;
import static android.service.notification.NotificationListenerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationListenerService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -1342,6 +1350,7 @@ public class NotificationManagerService extends SystemService {
@Override
void onPolicyChanged() {
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
mRankingHandler.requestSort();
}
});
mRankingHelper = new RankingHelper(getContext(),
@@ -1781,6 +1790,74 @@ public class NotificationManagerService extends SystemService {
UsageEvents.Event.NOTIFICATION_SEEN);
}
protected int calculateSuppressedVisualEffects(Policy incomingPolicy, Policy currPolicy,
int targetSdkVersion) {
if (incomingPolicy.suppressedVisualEffects == SUPPRESSED_EFFECTS_UNSET) {
return incomingPolicy.suppressedVisualEffects;
}
final int[] effectsIntroducedInP = {
SUPPRESSED_EFFECT_FULL_SCREEN_INTENT,
SUPPRESSED_EFFECT_LIGHTS,
SUPPRESSED_EFFECT_PEEK,
SUPPRESSED_EFFECT_STATUS_BAR,
SUPPRESSED_EFFECT_BADGE,
SUPPRESSED_EFFECT_AMBIENT,
SUPPRESSED_EFFECT_NOTIFICATION_LIST
};
int newSuppressedVisualEffects = incomingPolicy.suppressedVisualEffects;
if (targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
// unset higher order bits introduced in P, maintain the user's higher order bits
for (int i = 0; i < effectsIntroducedInP.length ; i++) {
newSuppressedVisualEffects &= ~effectsIntroducedInP[i];
newSuppressedVisualEffects |=
(currPolicy.suppressedVisualEffects & effectsIntroducedInP[i]);
}
// set higher order bits according to lower order bits
if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
}
if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
}
} else {
boolean hasNewEffects = (newSuppressedVisualEffects
- SUPPRESSED_EFFECT_SCREEN_ON - SUPPRESSED_EFFECT_SCREEN_OFF) > 0;
// if any of the new effects introduced in P are set
if (hasNewEffects) {
// clear out the deprecated effects
newSuppressedVisualEffects &= ~ (SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_SCREEN_OFF);
// set the deprecated effects according to the new more specific effects
if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_PEEK) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_ON;
}
if ((newSuppressedVisualEffects & Policy.SUPPRESSED_EFFECT_LIGHTS) != 0
&& (newSuppressedVisualEffects
& Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) != 0
&& (newSuppressedVisualEffects
& Policy.SUPPRESSED_EFFECT_AMBIENT) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_SCREEN_OFF;
}
} else {
// set higher order bits according to lower order bits
if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_OFF) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS;
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_AMBIENT;
}
if ((newSuppressedVisualEffects & SUPPRESSED_EFFECT_SCREEN_ON) != 0) {
newSuppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
}
}
}
return newSuppressedVisualEffects;
}
/**
* Report to usage stats that the notification was clicked.
* @param r notification record
@@ -3063,10 +3140,9 @@ public class NotificationManagerService extends SystemService {
try {
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(pkg,
0, UserHandle.getUserId(MY_UID));
Policy currPolicy = mZenModeHelper.getNotificationPolicy();
if (applicationInfo.targetSdkVersion <= Build.VERSION_CODES.O_MR1) {
Policy currPolicy = mZenModeHelper.getNotificationPolicy();
int priorityCategories = policy.priorityCategories;
// ignore alarm and media values from new policy
priorityCategories &= ~Policy.PRIORITY_CATEGORY_ALARMS;
@@ -3084,11 +3160,12 @@ public class NotificationManagerService extends SystemService {
policy.priorityCallSenders, policy.priorityMessageSenders,
policy.suppressedVisualEffects);
}
int newVisualEffects = calculateSuppressedVisualEffects(
policy, currPolicy, applicationInfo.targetSdkVersion);
policy = new Policy(policy.priorityCategories,
policy.priorityCallSenders, policy.priorityMessageSenders,
newVisualEffects);
Slog.i(TAG, "setNotificationPolicy pkg=" + pkg
+ " targetSdk=" + applicationInfo.targetSdkVersion
+ " policy="
+ Policy.priorityCategoriesToString(policy.priorityCategories));
mZenModeHelper.setNotificationPolicy(policy);
} catch (RemoteException e) {
} finally {
@@ -4465,8 +4542,7 @@ public class NotificationManagerService extends SystemService {
// release the light
boolean wasShowLights = mLights.remove(key);
if (record.getLight() != null && aboveThreshold
&& ((record.getSuppressedVisualEffects()
& NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) == 0)) {
&& ((record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_LIGHTS) == 0)) {
mLights.add(key);
updateLightsLocked();
if (mUseAttentionLight) {
@@ -4864,11 +4940,8 @@ public class NotificationManagerService extends SystemService {
private void applyZenModeLocked(NotificationRecord record) {
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
if (record.isIntercepted()) {
int suppressed = (mZenModeHelper.shouldSuppressWhenScreenOff()
? SUPPRESSED_EFFECT_SCREEN_OFF : 0)
| (mZenModeHelper.shouldSuppressWhenScreenOn()
? SUPPRESSED_EFFECT_SCREEN_ON : 0);
record.setSuppressedVisualEffects(suppressed);
record.setSuppressedVisualEffects(
mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
} else {
record.setSuppressedVisualEffects(0);
}

View File

@@ -16,8 +16,8 @@
package com.android.server.notification;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import android.content.Context;
import android.util.Log;
@@ -49,11 +49,8 @@ public class ZenModeExtractor implements NotificationSignalExtractor {
record.setIntercepted(mZenModeHelper.shouldIntercept(record));
if (record.isIntercepted()) {
int suppressed = (mZenModeHelper.shouldSuppressWhenScreenOff()
? SUPPRESSED_EFFECT_SCREEN_OFF : 0)
| (mZenModeHelper.shouldSuppressWhenScreenOn()
? SUPPRESSED_EFFECT_SCREEN_ON : 0);
record.setSuppressedVisualEffects(suppressed);
record.setSuppressedVisualEffects(
mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
} else {
record.setSuppressedVisualEffects(0);
}

View File

@@ -16,7 +16,10 @@
package com.android.server.notification;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioAttributes;
@@ -30,6 +33,8 @@ import android.telecom.TelecomManager;
import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.messages.nano.SystemMessageProto;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Objects;
@@ -104,6 +109,16 @@ public class ZenModeFiltering {
}
public boolean shouldIntercept(int zen, ZenModeConfig config, NotificationRecord record) {
if (zen == ZEN_MODE_OFF) {
return false;
}
// Make an exception to policy for the notification saying that policy has changed
if (NotificationManager.Policy.areAllVisualEffectsSuppressed(config.suppressedVisualEffects)
&& "android".equals(record.sbn.getPackageName())
&& SystemMessageProto.SystemMessage.NOTE_ZEN_UPGRADE == record.sbn.getId()) {
ZenLog.traceNotIntercepted(record, "systemDndChangedNotification");
return false;
}
switch (zen) {
case Global.ZEN_MODE_NO_INTERRUPTIONS:
// #notevenalarms

View File

@@ -602,7 +602,8 @@ public class ZenModeHelper {
pw.println(config);
return;
}
pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
+ "messages=%b,messagesFrom=%s,"
+ "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
config.allowAlarms, config.allowMedia, config.allowSystem,
config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
@@ -610,6 +611,7 @@ public class ZenModeHelper {
ZenModeConfig.sourceToString(config.allowMessagesFrom),
config.allowEvents, config.allowReminders, config.allowWhenScreenOff,
config.allowWhenScreenOn);
pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
if (config.automaticRules.isEmpty()) return;
final int N = config.automaticRules.size();
@@ -623,7 +625,7 @@ public class ZenModeHelper {
throws XmlPullParserException, IOException {
final ZenModeConfig config = ZenModeConfig.readXml(parser);
if (config != null) {
if (config.version < ZenModeConfig.XML_VERSION) {
if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
Settings.Global.putInt(mContext.getContentResolver(),
Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
}
@@ -1176,8 +1178,7 @@ public class ZenModeHelper {
@VisibleForTesting
protected Notification createZenUpgradeNotification() {
Intent intent = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS)
.setPackage("com.android.settings")
Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,

View File

@@ -18,10 +18,13 @@ package com.android.server.notification;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import android.app.ActivityManager;
import android.app.Notification;
@@ -149,4 +152,52 @@ public class BadgeExtractorTest extends UiServiceTestCase {
assertFalse(r.canShowBadge());
}
@Test
public void testDndOverridesYes() {
BadgeExtractor extractor = new BadgeExtractor();
extractor.setConfig(mConfig);
when(mConfig.badgingEnabled(mUser)).thenReturn(true);
when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
r.setIntercepted(true);
r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
extractor.process(r);
assertFalse(r.canShowBadge());
}
@Test
public void testDndOConsidersInterception() {
BadgeExtractor extractor = new BadgeExtractor();
extractor.setConfig(mConfig);
when(mConfig.badgingEnabled(mUser)).thenReturn(true);
when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
r.setIntercepted(false);
r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_BADGE);
extractor.process(r);
assertTrue(r.canShowBadge());
}
@Test
public void testDndConsidersSuppressedVisualEffects() {
BadgeExtractor extractor = new BadgeExtractor();
extractor.setConfig(mConfig);
when(mConfig.badgingEnabled(mUser)).thenReturn(true);
when(mConfig.canShowBadge(mPkg, mUid)).thenReturn(true);
NotificationRecord r = getNotificationRecord(true, IMPORTANCE_UNSPECIFIED);
r.setIntercepted(true);
r.setSuppressedVisualEffects(SUPPRESSED_EFFECT_LIGHTS);
extractor.process(r);
assertTrue(r.canShowBadge());
}
}

View File

@@ -22,8 +22,19 @@ import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.os.Build.VERSION_CODES.O_MR1;
import static android.os.Build.VERSION_CODES.P;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -2530,4 +2541,125 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(mAm, times(1)).revokeUriPermissionFromOwner(any(), eq(message1.getDataUri()),
anyInt(), anyInt());
}
@Test
public void testSetNotificationPolicy_preP_setOldFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
int expected = SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
assertEquals(expected, actual);
}
@Test
public void testSetNotificationPolicy_preP_setNewFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_NOTIFICATION_LIST);
int expected = SUPPRESSED_EFFECT_BADGE;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
assertEquals(expected, actual);
}
@Test
public void testSetNotificationPolicy_preP_setOldNewFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
int expected =
SUPPRESSED_EFFECT_BADGE | SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, O_MR1);
assertEquals(expected, actual);
}
@Test
public void testSetNotificationPolicy_P_setOldFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF);
int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
assertEquals(expected, actual);
}
@Test
public void testSetNotificationPolicy_P_setNewFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
assertEquals(expected, actual);
}
@Test
public void testSetNotificationPolicy_P_setOldNewFields() {
ZenModeHelper mZenModeHelper = mock(ZenModeHelper.class);
mService.mZenModeHelper = mZenModeHelper;
NotificationManager.Policy userPolicy =
new NotificationManager.Policy(0, 0, 0, SUPPRESSED_EFFECT_BADGE);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(userPolicy);
NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR);
int expected = SUPPRESSED_EFFECT_STATUS_BAR;
int actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
assertEquals(expected, actual);
appPolicy = new NotificationManager.Policy(0, 0, 0,
SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT);
expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
actual = mService.calculateSuppressedVisualEffects(appPolicy, userPolicy, P);
assertEquals(expected, actual);
}
}

View File

@@ -17,6 +17,8 @@
package com.android.server.notification;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -57,6 +59,8 @@ public class ZenModeExtractorTest extends UiServiceTestCase {
assertFalse(r.isIntercepted());
when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(
new NotificationManager.Policy(0,0,0));
extractor.process(r);
@@ -70,7 +74,8 @@ public class ZenModeExtractorTest extends UiServiceTestCase {
NotificationRecord r = generateRecord();
when(mZenModeHelper.shouldIntercept(any())).thenReturn(false);
when(mZenModeHelper.shouldSuppressWhenScreenOff()).thenReturn(false);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(
new NotificationManager.Policy(0,0,0));
extractor.process(r);
@@ -84,13 +89,14 @@ public class ZenModeExtractorTest extends UiServiceTestCase {
NotificationRecord r = generateRecord();
when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
when(mZenModeHelper.shouldSuppressWhenScreenOff()).thenReturn(true);
when(mZenModeHelper.shouldSuppressWhenScreenOn()).thenReturn(true);
when(mZenModeHelper.getNotificationPolicy()).thenReturn(
new NotificationManager.Policy(0,0,0, SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST));
extractor.process(r);
assertEquals(NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF
| NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON,
assertEquals(NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK
| NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST,
r.getSuppressedVisualEffects());
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2018 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 distriZenbuted 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.server.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.server.UiServiceTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class ZenModeFilteringTest extends UiServiceTestCase {
private ZenModeFiltering mZenModeFiltering;
@Before
public void setUp() {
mZenModeFiltering = new ZenModeFiltering(mContext);
}
private NotificationRecord getNotificationRecord() {
StatusBarNotification sbn = mock(StatusBarNotification.class);
when(sbn.getNotification()).thenReturn(mock(Notification.class));
return new NotificationRecord(mContext, sbn, mock(NotificationChannel.class));
}
@Test
public void testSuppressDNDInfo_yes_VisEffectsAllowed() {
NotificationRecord r = getNotificationRecord();
when(r.sbn.getPackageName()).thenReturn("android");
when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
ZenModeConfig config = mock(ZenModeConfig.class);
config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects()
- SUPPRESSED_EFFECT_STATUS_BAR;
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
}
@Test
public void testSuppressDNDInfo_yes_WrongId() {
NotificationRecord r = getNotificationRecord();
when(r.sbn.getPackageName()).thenReturn("android");
when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION);
ZenModeConfig config = mock(ZenModeConfig.class);
config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
}
@Test
public void testSuppressDNDInfo_yes_WrongPackage() {
NotificationRecord r = getNotificationRecord();
when(r.sbn.getPackageName()).thenReturn("android2");
when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
ZenModeConfig config = mock(ZenModeConfig.class);
config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
}
@Test
public void testSuppressDNDInfo_no() {
NotificationRecord r = getNotificationRecord();
when(r.sbn.getPackageName()).thenReturn("android");
when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
ZenModeConfig config = mock(ZenModeConfig.class);
config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, config, r));
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
}
@Test
public void testSuppressAnything_yes_ZenModeOff() {
NotificationRecord r = getNotificationRecord();
when(r.sbn.getPackageName()).thenReturn("bananas");
ZenModeConfig config = mock(ZenModeConfig.class);
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, config, r));
}
}

View File

@@ -16,6 +16,8 @@
package com.android.server.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
@@ -34,6 +36,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
@@ -48,8 +51,11 @@ import android.service.notification.ZenModeConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.Xml;
import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
import android.util.Slog;
@@ -58,6 +64,13 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -80,12 +93,27 @@ public class ZenModeHelperTest extends UiServiceTestCase {
mContext = spy(getContext());
mContentResolver = mContext.getContentResolver();
when(mContext.getResources()).thenReturn(mResources);
when(mResources.getString(R.string.zen_mode_default_every_night_name)).thenReturn("night");
when(mResources.getString(R.string.zen_mode_default_events_name)).thenReturn("events");
when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
mConditionProviders));
}
private ByteArrayOutputStream writeXmlAndPurge(boolean forBackup)
throws Exception {
XmlSerializer serializer = new FastXmlSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
serializer.startDocument(null, true);
mZenModeHelperSpy.writeXml(serializer, forBackup);
serializer.endDocument();
serializer.flush();
mZenModeHelperSpy.setConfig(new ZenModeConfig(), "writing xml");
return baos;
}
@Test
public void testZenOff_NoMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
@@ -497,4 +525,71 @@ public class ZenModeHelperTest extends UiServiceTestCase {
verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
@Test
public void testParcelConfig() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
mZenModeHelperSpy.mConfig.allowReminders = true;
mZenModeHelperSpy.mConfig.allowCalls = true;
mZenModeHelperSpy.mConfig.allowMessages = true;
mZenModeHelperSpy.mConfig.allowEvents = true;
mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
mZenModeHelperSpy.mConfig.manualRule.enabled = true;
mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
ZenModeConfig actual = mZenModeHelperSpy.mConfig.copy();
assertEquals(mZenModeHelperSpy.mConfig, actual);
}
@Test
public void testWriteXml() throws Exception {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
mZenModeHelperSpy.mConfig.allowReminders = true;
mZenModeHelperSpy.mConfig.allowCalls = true;
mZenModeHelperSpy.mConfig.allowMessages = true;
mZenModeHelperSpy.mConfig.allowEvents = true;
mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
mZenModeHelperSpy.mConfig.manualRule.zenMode =
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
mZenModeHelperSpy.mConfig.manualRule.enabled = true;
mZenModeHelperSpy.mConfig.manualRule.snoozing = true;
ZenModeConfig expected = mZenModeHelperSpy.mConfig.copy();
ByteArrayOutputStream baos = writeXmlAndPurge(false);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(expected, mZenModeHelperSpy.mConfig);
}
@Test
public void testPolicyReadsSuppressedEffects() {
mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
NotificationManager.Policy policy = mZenModeHelperSpy.getNotificationPolicy();
assertEquals(SUPPRESSED_EFFECT_BADGE, policy.suppressedVisualEffects);
}
}