blob: 702161e48b75048eabc38fa2f68a90673624356d [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is 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_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_PEEK;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertEquals;
import static junit.framework.TestCase.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
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.AppGlobals;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.VolumePolicy;
import android.media.AudioSystem;
import android.net.Uri;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Xml;
import com.android.internal.R;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.server.notification.ManagedServices.UserProfiles;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
import org.junit.Before;
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.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class ZenModeHelperTest extends UiServiceTestCase {
ConditionProviders mConditionProviders;
@Mock NotificationManager mNotificationManager;
private Resources mResources;
private TestableLooper mTestableLooper;
private ZenModeHelper mZenModeHelperSpy;
private Context mContext;
private ContentResolver mContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
mContext = spy(getContext());
mContentResolver = mContext.getContentResolver();
mResources = spy(mContext.getResources());
try {
when(mResources.getXml(R.xml.default_zen_mode_config)).thenReturn(
getDefaultConfigParser());
} catch (Exception e) {
Log.d("ZenModeHelperTest", "Couldn't mock default zen mode config xml file err=" +
e.toString());
}
when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
mConditionProviders = new ConditionProviders(mContext, new UserProfiles(),
AppGlobals.getPackageManager());
mConditionProviders.addSystemProvider(new CountdownConditionProvider());
mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
mConditionProviders));
}
private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
String xml = "<zen version=\"8\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"true\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<automatic ruleId=\"EVENTS_DEFAULT_RULE\" enabled=\"false\" snoozing=\"false\""
+ " name=\"Event\" zen=\"1\""
+ " component=\"android/com.android.server.notification.EventConditionProvider\""
+ " conditionId=\"condition://android/event?userId=-10000&amp;calendar=&amp;"
+ "reply=1\"/>\n"
+ "<automatic ruleId=\"EVERY_NIGHT_DEFAULT_RULE\" enabled=\"false\""
+ " snoozing=\"false\" name=\"Sleeping\" zen=\"1\""
+ " component=\"android/com.android.server.notification.ScheduleConditionProvider\""
+ " conditionId=\"condition://android/schedule?days=1.2.3.4.5.6.7 &amp;start=22.0"
+ "&amp;end=7.0&amp;exitAtAlarm=true\"/>"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
return new XmlResourceParserImpl(parser);
}
private ByteArrayOutputStream writeXmlAndPurge(boolean forBackup, Integer version)
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, version);
serializer.endDocument();
serializer.flush();
mZenModeHelperSpy.setConfig(new ZenModeConfig(), null, "writing xml");
return baos;
}
@Test
public void testZenOff_NoMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
mZenModeHelperSpy.applyRestrictions();
doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyInt());
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_ALARM);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_MEDIA);
}
@Test
public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
assertTrue(mZenModeHelperSpy.mConfig.allowMedia);
mZenModeHelperSpy.applyRestrictions();
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_ALARM);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_MEDIA);
}
@Test
public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
assertFalse(mZenModeHelperSpy.mConfig.allowSystem);
mZenModeHelperSpy.applyRestrictions();
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_ALARM);
// Media is a catch-all that includes games
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_MEDIA);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_GAME);
}
@Test
public void testTotalSilence() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
mZenModeHelperSpy.applyRestrictions();
// Total silence will silence alarms, media and system noises (but not vibrations)
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_ALARM);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_MEDIA);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_GAME);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_UNKNOWN);
}
@Test
public void testAlarmsOnly_alarmMediaMuteNotApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
mZenModeHelperSpy.applyRestrictions();
// Alarms only mode will not silence alarms
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_ALARM);
// Alarms only mode will not silence media
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_MEDIA);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_GAME);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_UNKNOWN);
// Alarms only will silence system noises (but not vibrations)
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
}
@Test
public void testAlarmsOnly_callsMuteApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
mZenModeHelperSpy.mConfig.allowCalls = true;
assertTrue(mZenModeHelperSpy.mConfig.allowCalls);
mZenModeHelperSpy.applyRestrictions();
// Alarms only mode will silence calls despite priority-mode config
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
}
@Test
public void testAlarmsOnly_allZenConfigToggledCannotBypass_alarmMuteNotApplied() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
mZenModeHelperSpy.mConfig.allowReminders = false;
mZenModeHelperSpy.mConfig.allowCalls = false;
mZenModeHelperSpy.mConfig.allowMessages = false;
mZenModeHelperSpy.mConfig.allowEvents = false;
mZenModeHelperSpy.mConfig.allowRepeatCallers= false;
assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
assertFalse(mZenModeHelperSpy.mConfig.allowReminders);
assertFalse(mZenModeHelperSpy.mConfig.allowCalls);
assertFalse(mZenModeHelperSpy.mConfig.allowMessages);
assertFalse(mZenModeHelperSpy.mConfig.allowEvents);
assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers);
mZenModeHelperSpy.applyRestrictions();
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_ALARM);
}
@Test
public void testZenAllCannotBypass() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
// with special case USAGE_ASSISTANCE_SONIFICATION
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
mZenModeHelperSpy.mConfig.allowReminders = false;
mZenModeHelperSpy.mConfig.allowCalls = false;
mZenModeHelperSpy.mConfig.allowMessages = false;
mZenModeHelperSpy.mConfig.allowEvents = false;
mZenModeHelperSpy.mConfig.allowRepeatCallers= false;
assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
assertFalse(mZenModeHelperSpy.mConfig.allowReminders);
assertFalse(mZenModeHelperSpy.mConfig.allowCalls);
assertFalse(mZenModeHelperSpy.mConfig.allowMessages);
assertFalse(mZenModeHelperSpy.mConfig.allowEvents);
assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers);
mZenModeHelperSpy.applyRestrictions();
for (int usage : AudioAttributes.SDK_USAGES) {
if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
// only mute audio, not vibrations
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
AppOpsManager.OP_PLAY_AUDIO);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
AppOpsManager.OP_VIBRATE);
} else {
boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
!= AudioAttributes.SUPPRESSIBLE_NEVER;
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
}
}
}
@Test
public void testZenUpgradeNotification() {
// shows zen upgrade notification if stored settings says to shows,
// zen has not been updated, boot is completed
// and we're setting zen mode on
Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
mZenModeHelperSpy.mIsBootComplete = true;
mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification();
verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG),
eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
assertEquals(0, Settings.Secure.getInt(mContentResolver,
Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, -1));
}
@Test
public void testNoZenUpgradeNotification() {
// doesn't show upgrade notification if stored settings says don't show
Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
mZenModeHelperSpy.mIsBootComplete = true;
mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
}
@Test
public void testNoZenUpgradeNotificationZenUpdated() {
// doesn't show upgrade notification since zen was already updated
Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
mZenModeHelperSpy.mIsBootComplete = true;
mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
eq(SystemMessage.NOTE_ZEN_UPGRADE), any());
}
@Test
public void testZenSetInternalRinger_AllPriorityNotificationSoundsMuted() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
Integer.toString(AudioManager.RINGER_MODE_NORMAL));
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
// Set zen to priority-only with all notification sounds muted (so ringer will be muted)
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = false;
mZenModeHelperSpy.mConfig.allowCalls = false;
mZenModeHelperSpy.mConfig.allowMessages = false;
mZenModeHelperSpy.mConfig.allowEvents = false;
mZenModeHelperSpy.mConfig.allowRepeatCallers= false;
// 2. apply priority only zen - verify ringer is unchanged
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_SILENT,
mZenModeHelperSpy.TAG);
// 3. apply zen off - verify zen is set to previous ringer (normal)
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
@Test
public void testRingerAffectedStreamsTotalSilence() {
// in total silence:
// ringtone, notification, system, alarm, streams, music are affected by ringer mode
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
ZenModeHelper.RingerModeDelegate ringerModeDelegate =
mZenModeHelperSpy.new RingerModeDelegate();
int ringerModeAffectedStreams = ringerModeDelegate.getRingerModeAffectedStreams(0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_RING)) != 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_NOTIFICATION))
!= 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_SYSTEM)) != 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_ALARM)) != 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_MUSIC)) != 0);
}
@Test
public void testRingerAffectedStreamsPriorityOnly() {
// in priority only mode:
// ringtone, notification and system streams are affected by ringer mode
// UNLESS ringer is muted due to all the other priority only dnd sounds being muted
mZenModeHelperSpy.mConfig.allowAlarms = true;
mZenModeHelperSpy.mConfig.allowReminders = true;
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
ZenModeHelper.RingerModeDelegate ringerModeDelegateRingerMuted =
mZenModeHelperSpy.new RingerModeDelegate();
int ringerModeAffectedStreams =
ringerModeDelegateRingerMuted.getRingerModeAffectedStreams(0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_RING)) != 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_NOTIFICATION))
!= 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_SYSTEM)) != 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_ALARM)) == 0);
assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_MUSIC)) == 0);
// special case: if ringer is muted (since all notification sounds cannot bypass)
// then system stream is not affected by ringer mode
mZenModeHelperSpy.mConfig.allowReminders = false;
mZenModeHelperSpy.mConfig.allowCalls = false;
mZenModeHelperSpy.mConfig.allowMessages = false;
mZenModeHelperSpy.mConfig.allowEvents = false;
mZenModeHelperSpy.mConfig.allowRepeatCallers= false;
ZenModeHelper.RingerModeDelegate ringerModeDelegateRingerNotMuted =
mZenModeHelperSpy.new RingerModeDelegate();
int ringerMutedRingerModeAffectedStreams =
ringerModeDelegateRingerNotMuted.getRingerModeAffectedStreams(0);
assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_RING)) != 0);
assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_NOTIFICATION))
!= 0);
assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_SYSTEM))
== 0);
assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_ALARM)) == 0);
assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_MUSIC)) == 0);
}
@Test
public void testZenSetInternalRinger_NotAllPriorityNotificationSoundsMuted_StartNormal() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
Integer.toString(AudioManager.RINGER_MODE_NORMAL));
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify ringer is normal
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
// 3. apply zen off - verify ringer remains normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
@Test
public void testZenSetInternalRinger_NotAllPriorityNotificationSoundsMuted_StartSilent() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
Integer.toString(AudioManager.RINGER_MODE_SILENT));
// 1. Current ringer is silent
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify ringer is silent
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_SILENT,
mZenModeHelperSpy.TAG);
// 3. apply zen-off - verify ringer is still silent
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_SILENT,
mZenModeHelperSpy.TAG);
}
@Test
public void testZenSetInternalRinger_NotAllPriorityNotificationSoundsMuted_RingerChanges() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
Integer.toString(AudioManager.RINGER_MODE_NORMAL));
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
// Set zen to priority-only with all notification sounds muted (so ringer will be muted)
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify zen will still be normal
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
// 3. change ringer from normal to silent, verify previous ringer set to new ringer (silent)
ZenModeHelper.RingerModeDelegate ringerModeDelegate =
mZenModeHelperSpy.new RingerModeDelegate();
ringerModeDelegate.onSetRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
AudioManager.RINGER_MODE_SILENT, "test", AudioManager.RINGER_MODE_NORMAL,
VolumePolicy.DEFAULT);
assertEquals(AudioManager.RINGER_MODE_SILENT, Global.getInt(mContext.getContentResolver(),
Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL));
// 4. apply zen off - verify ringer still silenced
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelperSpy.applyZenToRingerMode();
verify(mAudioManager, atLeastOnce()).setRingerModeInternal(AudioManager.RINGER_MODE_SILENT,
mZenModeHelperSpy.TAG);
}
@Test
public void testSilentRingerSavedInZenOff_startsZenOff() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
// apply zen off multiple times - verify ringer is not set to normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
mZenModeHelperSpy.mConfig = null; // will evaluate config to zen mode off
for (int i = 0; i < 3; i++) {
// if zen doesn't change, zen should not reapply itself to the ringer
mZenModeHelperSpy.evaluateZenMode("test", true);
}
verify(mZenModeHelperSpy, never()).applyZenToRingerMode();
verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
@Test
public void testSilentRingerSavedOnZenOff_startsZenOn() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
// previously set silent ringer
ZenModeHelper.RingerModeDelegate ringerModeDelegate =
mZenModeHelperSpy.new RingerModeDelegate();
ringerModeDelegate.onSetRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
AudioManager.RINGER_MODE_SILENT, "test", AudioManager.RINGER_MODE_NORMAL,
VolumePolicy.DEFAULT);
assertEquals(AudioManager.RINGER_MODE_SILENT, Global.getInt(mContext.getContentResolver(),
Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL));
// apply zen off multiple times - verify ringer is not set to normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig = null; // will evaluate config to zen mode off
for (int i = 0; i < 3; i++) {
// if zen doesn't change, zen should not reapply itself to the ringer
mZenModeHelperSpy.evaluateZenMode("test", true);
}
verify(mZenModeHelperSpy, times(1)).applyZenToRingerMode();
verify(mAudioManager, never()).setRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
mZenModeHelperSpy.TAG);
}
@Test
public void testVibrateRingerSavedOnZenOff_startsZenOn() {
AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
mZenModeHelperSpy.mAudioManager = mAudioManager;
mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
// previously set silent ringer
ZenModeHelper.RingerModeDelegate ringerModeDelegate =
mZenModeHelperSpy.new RingerModeDelegate();
ringerModeDelegate.onSetRingerModeInternal(AudioManager.RINGER_MODE_NORMAL,
AudioManager.RINGER_MODE_VIBRATE, "test", AudioManager.RINGER_MODE_NORMAL,
VolumePolicy.DEFAULT);
assertEquals(AudioManager.RINGER_MODE_VIBRATE, Global.getInt(mContext.getContentResolver(),
Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL));
// apply zen off multiple times - verify ringer is not set to normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig = null; // will evaluate config to zen mode off
for (int i = 0; i < 3; i++) {
// if zen doesn't change, zen should not reapply itself to the ringer
mZenModeHelperSpy.evaluateZenMode("test", true);
}
verify(mZenModeHelperSpy, times(1)).applyZenToRingerMode();
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.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.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, null);
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 testReadXmlRestore() throws Exception {
setupZenConfig();
// one enabled automatic rule
ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo customRuleInfo = new ScheduleInfo();
customRule.enabled = true;
customRule.creationTime = 0;
customRule.id = "customRule";
customRule.name = "Custom Rule";
customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
automaticRules.put("customRule", customRule);
mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
ZenModeConfig original = mZenModeHelperSpy.mConfig.copy();
ByteArrayOutputStream baos = writeXmlAndPurge(false, null);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, true);
assertEquals(original, mZenModeHelperSpy.mConfig);
assertEquals(original.hashCode(), mZenModeHelperSpy.mConfig.hashCode());
}
@Test
public void testReadXmlRulesNotOverriden() throws Exception {
setupZenConfig();
// automatic zen rule is enabled on upgrade so rules should not be overriden to default
ArrayMap<String, ZenModeConfig.ZenRule> enabledAutoRule = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo weeknights = new ScheduleInfo();
customRule.enabled = true;
customRule.name = "Custom Rule";
customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
enabledAutoRule.put("customRule", customRule);
mZenModeHelperSpy.mConfig.automaticRules = enabledAutoRule;
// set previous version
ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertTrue(mZenModeHelperSpy.mConfig.automaticRules.containsKey("customRule"));
setupZenConfigMaintained();
}
@Test
public void testMigrateSuppressedVisualEffects_oneExistsButOff() throws Exception {
String xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"true\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOn=\"true\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
}
@Test
public void testMigrateSuppressedVisualEffects_bothExistButOff() throws Exception {
String xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"true\" visualScreenOn=\"true\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
}
@Test
public void testMigrateSuppressedVisualEffects_bothExistButOn() throws Exception {
String xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"false\" visualScreenOn=\"false\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK,
mZenModeHelperSpy.mConfig.suppressedVisualEffects);
xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"true\" visualScreenOn=\"false\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(SUPPRESSED_EFFECT_PEEK, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
xml = "<zen version=\"6\" user=\"0\">\n"
+ "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+ "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+ "visualScreenOff=\"false\" visualScreenOn=\"true\" alarms=\"true\" "
+ "media=\"true\" system=\"false\" />\n"
+ "<disallow visualEffects=\"511\" />"
+ "</zen>";
parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(xml.getBytes())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
assertEquals(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_LIGHTS,
mZenModeHelperSpy.mConfig.suppressedVisualEffects);
}
@Test
public void testReadXmlResetDefaultRules() throws Exception {
setupZenConfig();
// no enabled automatic zen rules and no default rules
// so rules should be overriden by default rules
mZenModeHelperSpy.mConfig.automaticRules = new ArrayMap<>();
// set previous version
ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
// check default rules
ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
assertTrue(rules.size() != 0);
for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
assertTrue(rules.containsKey(defaultId));
}
setupZenConfigMaintained();
}
@Test
public void testReadXmlAllDisabledRulesResetDefaultRules() throws Exception {
setupZenConfig();
// all automatic zen rules are disabled on upgrade (and default rules don't already exist)
// so rules should be overriden by default rules
ArrayMap<String, ZenModeConfig.ZenRule> disabledAutoRule = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo weeknights = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
disabledAutoRule.put("customRule", customRule);
mZenModeHelperSpy.mConfig.automaticRules = disabledAutoRule;
// set previous version
ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
// check default rules
ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
assertTrue(rules.size() != 0);
for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
assertTrue(rules.containsKey(defaultId));
}
assertFalse(rules.containsKey("customRule"));
setupZenConfigMaintained();
}
@Test
public void testReadXmlOnlyOneDefaultRuleExists() throws Exception {
setupZenConfig();
// all automatic zen rules are disabled on upgrade and only one default rule exists
// so rules should be overriden to the default rules
ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo customRuleInfo = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
automaticRules.put("customRule", customRule);
ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule();
final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
defaultScheduleRule.enabled = false;
defaultScheduleRule.name = "Default Schedule Rule";
defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultScheduleRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule);
mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
// set previous version
ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
// check default rules
ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
assertTrue(rules.size() != 0);
for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
assertTrue(rules.containsKey(defaultId));
}
assertFalse(rules.containsKey("customRule"));
setupZenConfigMaintained();
}
@Test
public void testReadXmlDefaultRulesExist() throws Exception {
setupZenConfig();
// Default rules exist so rules should not be overridden by defaults
ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo customRuleInfo = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
automaticRules.put("customRule", customRule);
ZenModeConfig.ZenRule defaultScheduleRule = new ZenModeConfig.ZenRule();
final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
defaultScheduleRule.enabled = false;
defaultScheduleRule.name = "Default Schedule Rule";
defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultScheduleRuleInfo);
defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
automaticRules.put(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID, defaultScheduleRule);
ZenModeConfig.ZenRule defaultEventRule = new ZenModeConfig.ZenRule();
final ScheduleInfo defaultEventRuleInfo = new ScheduleInfo();
defaultEventRule.enabled = false;
defaultEventRule.name = "Default Event Rule";
defaultEventRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultEventRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultEventRuleInfo);
defaultEventRule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
automaticRules.put(ZenModeConfig.EVENTS_DEFAULT_RULE_ID, defaultEventRule);
mZenModeHelperSpy.mConfig.automaticRules = automaticRules;
// set previous version
ByteArrayOutputStream baos = writeXmlAndPurge(false, 5);
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new BufferedInputStream(
new ByteArrayInputStream(baos.toByteArray())), null);
parser.nextTag();
mZenModeHelperSpy.readXml(parser, false);
// check default rules
ArrayMap<String, ZenModeConfig.ZenRule> rules = mZenModeHelperSpy.mConfig.automaticRules;
assertTrue(rules.size() != 0);
for (String defaultId : ZenModeConfig.DEFAULT_RULE_IDS) {
assertTrue(rules.containsKey(defaultId));
}
assertTrue(rules.containsKey("customRule"));
setupZenConfigMaintained();
}
@Test
public void testCountdownConditionSubscription() throws Exception {
ZenModeConfig config = new ZenModeConfig();
mZenModeHelperSpy.mConfig = config;
mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true);
assertEquals(0, mZenModeHelperSpy.mConditions.mSubscriptions.size());
mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
Uri conditionId = ZenModeConfig.toCountdownConditionId(9000000, false);
mZenModeHelperSpy.mConfig.manualRule.conditionId = conditionId;
mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("android",
CountdownConditionProvider.class.getName());
mZenModeHelperSpy.mConfig.manualRule.condition = new Condition(conditionId, "", "", "", 0,
Condition.STATE_TRUE, Condition.FLAG_RELEVANT_NOW);
mZenModeHelperSpy.mConfig.manualRule.enabled = true;
ZenModeConfig originalConfig = mZenModeHelperSpy.mConfig.copy();
mZenModeHelperSpy.mConditions.evaluateConfig(mZenModeHelperSpy.mConfig, null, true);
assertEquals(true, ZenModeConfig.isValidCountdownConditionId(conditionId));
assertEquals(originalConfig, mZenModeHelperSpy.mConfig);
assertEquals(1, mZenModeHelperSpy.mConditions.mSubscriptions.size());
}
private void setupZenConfig() {
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.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
mZenModeHelperSpy.mConfig.manualRule = null;
}
private void setupZenConfigMaintained() {
// config is still the same as when it was setup (setupZenConfig)
assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
assertFalse(mZenModeHelperSpy.mConfig.allowSystem);
assertTrue(mZenModeHelperSpy.mConfig.allowReminders);
assertTrue(mZenModeHelperSpy.mConfig.allowCalls);
assertTrue(mZenModeHelperSpy.mConfig.allowMessages);
assertTrue(mZenModeHelperSpy.mConfig.allowEvents);
assertTrue(mZenModeHelperSpy.mConfig.allowRepeatCallers);
assertEquals(SUPPRESSED_EFFECT_BADGE, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
}
/**
* Wrapper to use XmlPullParser as XmlResourceParser for Resources.getXml()
*/
final class XmlResourceParserImpl implements XmlResourceParser {
private XmlPullParser parser;
public XmlResourceParserImpl(XmlPullParser parser) {
this.parser = parser;
}
public int getEventType() throws XmlPullParserException {
return parser.getEventType();
}
@Override
public void setFeature(String name, boolean state) throws XmlPullParserException {
parser.setFeature(name, state);
}
@Override
public boolean getFeature(String name) {
return false;
}
@Override
public void setProperty(String name, Object value) throws XmlPullParserException {
parser.setProperty(name, value);
}
@Override
public Object getProperty(String name) {
return parser.getProperty(name);
}
@Override
public void setInput(Reader in) throws XmlPullParserException {
parser.setInput(in);
}
@Override
public void setInput(InputStream inputStream, String inputEncoding)
throws XmlPullParserException {
parser.setInput(inputStream, inputEncoding);
}
@Override
public String getInputEncoding() {
return parser.getInputEncoding();
}
@Override
public void defineEntityReplacementText(String entityName, String replacementText)
throws XmlPullParserException {
parser.defineEntityReplacementText(entityName, replacementText);
}
@Override
public int getNamespaceCount(int depth) throws XmlPullParserException {
return parser.getNamespaceCount(depth);
}
@Override
public String getNamespacePrefix(int pos) throws XmlPullParserException {
return parser.getNamespacePrefix(pos);
}
@Override
public String getNamespaceUri(int pos) throws XmlPullParserException {
return parser.getNamespaceUri(pos);
}
@Override
public String getNamespace(String prefix) {
return parser.getNamespace(prefix);
}
@Override
public int getDepth() {
return parser.getDepth();
}
@Override
public String getPositionDescription() {
return parser.getPositionDescription();
}
@Override
public int getLineNumber() {
return parser.getLineNumber();
}
@Override
public int getColumnNumber() {
return parser.getColumnNumber();
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
return parser.isWhitespace();
}
@Override
public String getText() {
return parser.getText();
}
@Override
public char[] getTextCharacters(int[] holderForStartAndLength) {
return parser.getTextCharacters(holderForStartAndLength);
}
@Override
public String getNamespace() {
return parser.getNamespace();
}
@Override
public String getName() {
return parser.getName();
}
@Override
public String getPrefix() {
return parser.getPrefix();
}
@Override
public boolean isEmptyElementTag() throws XmlPullParserException {
return false;
}
@Override
public int getAttributeCount() {
return parser.getAttributeCount();
}
public int next() throws IOException, XmlPullParserException {
return parser.next();
}
@Override
public int nextToken() throws XmlPullParserException, IOException {
return parser.next();
}
@Override
public void require(int type, String namespace, String name)
throws XmlPullParserException, IOException {
parser.require(type, namespace, name);
}
@Override
public String nextText() throws XmlPullParserException, IOException {
return parser.nextText();
}
@Override
public String getAttributeNamespace(int index) {
return "";
}
@Override
public String getAttributeName(int index) {
return parser.getAttributeName(index);
}
@Override
public String getAttributePrefix(int index) {
return parser.getAttributePrefix(index);
}
@Override
public String getAttributeType(int index) {
return parser.getAttributeType(index);
}
@Override
public boolean isAttributeDefault(int index) {
return parser.isAttributeDefault(index);
}
@Override
public String getAttributeValue(int index) {
return parser.getAttributeValue(index);
}
@Override
public String getAttributeValue(String namespace, String name) {
return parser.getAttributeValue(namespace, name);
}
@Override
public int getAttributeNameResource(int index) {
return 0;
}
@Override
public int getAttributeListValue(String namespace, String attribute, String[] options,
int defaultValue) {
return 0;
}
@Override
public boolean getAttributeBooleanValue(String namespace, String attribute,
boolean defaultValue) {
return false;
}
@Override
public int getAttributeResourceValue(String namespace, String attribute, int defaultValue) {
return 0;
}
@Override
public int getAttributeIntValue(String namespace, String attribute, int defaultValue) {
return 0;
}
@Override
public int getAttributeUnsignedIntValue(String namespace, String attribute,
int defaultValue) {
return 0;
}
@Override
public float getAttributeFloatValue(String namespace, String attribute,
float defaultValue) {
return 0;
}
@Override
public int getAttributeListValue(int index, String[] options, int defaultValue) {
return 0;
}
@Override
public boolean getAttributeBooleanValue(int index, boolean defaultValue) {
return false;
}
@Override
public int getAttributeResourceValue(int index, int defaultValue) {
return 0;
}
@Override
public int getAttributeIntValue(int index, int defaultValue) {
return 0;
}
@Override
public int getAttributeUnsignedIntValue(int index, int defaultValue) {
return 0;
}
@Override
public float getAttributeFloatValue(int index, float defaultValue) {
return 0;
}
@Override
public String getIdAttribute() {
return null;
}
@Override
public String getClassAttribute() {
return null;
}
@Override
public int getIdAttributeResourceValue(int defaultValue) {
return 0;
}
@Override
public int getStyleAttribute() {
return 0;
}
@Override
public void close() {
}
@Override
public int nextTag() throws IOException, XmlPullParserException {
return parser.nextTag();
}
}
}