ZenModeConfig.java revision 530052a2fe3b6a6a4246ce28ab0ced647fe7f470
1f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose/** 2740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * Copyright (c) 2014, The Android Open Source Project 3740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * 4740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * Licensed under the Apache License, Version 2.0 (the "License"); 5740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * you may not use this file except in compliance with the License. 6740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * You may obtain a copy of the License at 7740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * 8740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * http://www.apache.org/licenses/LICENSE-2.0 9740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * 10740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * Unless required by applicable law or agreed to in writing, software 11740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * distributed under the License is distributed on an "AS IS" BASIS, 12740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * See the License for the specific language governing permissions and 14740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * limitations under the License. 15740d490593e0de8732a697c9f77b90ddd463863bJordan Rose */ 16740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 17740d490593e0de8732a697c9f77b90ddd463863bJordan Rosepackage android.service.notification; 18740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 19740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.content.ComponentName; 20740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.content.Context; 21740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.content.res.Resources; 22740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.net.Uri; 23de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Roseimport android.os.Parcel; 24740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.os.Parcelable; 25b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Roseimport android.text.TextUtils; 26740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.text.format.DateFormat; 27740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport android.util.Slog; 2828038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose 2928038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseimport org.xmlpull.v1.XmlPullParser; 3028038f33aa2db4833881fea757a1f0daf85ac02bJordan Roseimport org.xmlpull.v1.XmlPullParserException; 31740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport org.xmlpull.v1.XmlSerializer; 32740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 33740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport java.io.IOException; 34740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport java.util.ArrayList; 35740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport java.util.Arrays; 36fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Roseimport java.util.Calendar; 37c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Roseimport java.util.Locale; 38c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Roseimport java.util.Objects; 39740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 40740d490593e0de8732a697c9f77b90ddd463863bJordan Roseimport com.android.internal.R; 41740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 42740d490593e0de8732a697c9f77b90ddd463863bJordan Rose/** 438d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose * Persisted configuration for zen mode. 4470cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose * 45740d490593e0de8732a697c9f77b90ddd463863bJordan Rose * @hide 4670cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose */ 478919e688dc610d1f632a4d43f7f1489f67255476Jordan Rosepublic class ZenModeConfig implements Parcelable { 48740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static String TAG = "ZenModeConfig"; 49740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 50b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static final String SLEEP_MODE_NIGHTS = "nights"; 51740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights"; 52740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final String SLEEP_MODE_DAYS_PREFIX = "days:"; 53740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 54740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final int SOURCE_ANYONE = 0; 55740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final int SOURCE_CONTACT = 1; 56740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final int SOURCE_STAR = 2; 57b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static final int MAX_SOURCE = SOURCE_STAR; 587c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 597c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static final int[] ALL_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, 60b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose Calendar.WEDNESDAY, Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY }; 61b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static final int[] WEEKNIGHT_DAYS = { Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, 627c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose Calendar.WEDNESDAY, Calendar.THURSDAY }; 637c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 647c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 }; 657c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final int SECONDS_MS = 1000; 66740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final int MINUTES_MS = 60 * SECONDS_MS; 67b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final int ZERO_VALUE_MS = 10 * SECONDS_MS; 68b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 69b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final boolean DEFAULT_ALLOW_EVENTS = true; 70b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 717c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final int XML_VERSION = 1; 727c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String ZEN_TAG = "zen"; 73b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String ZEN_ATT_VERSION = "version"; 747c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String ALLOW_TAG = "allow"; 757c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String ALLOW_ATT_CALLS = "calls"; 76b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String ALLOW_ATT_MESSAGES = "messages"; 777c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String ALLOW_ATT_FROM = "from"; 787c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String ALLOW_ATT_EVENTS = "events"; 79b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String SLEEP_TAG = "sleep"; 80b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String SLEEP_ATT_MODE = "mode"; 81b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String SLEEP_ATT_NONE = "none"; 827c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 83b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String SLEEP_ATT_START_HR = "startHour"; 84740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String SLEEP_ATT_START_MIN = "startMin"; 85740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String SLEEP_ATT_END_HR = "endHour"; 86740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String SLEEP_ATT_END_MIN = "endMin"; 87740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 88b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose private static final String CONDITION_TAG = "condition"; 89740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_COMPONENT = "component"; 90740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_ID = "id"; 91740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_SUMMARY = "summary"; 92740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_LINE1 = "line1"; 93740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_LINE2 = "line2"; 94740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_ICON = "icon"; 957c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static final String CONDITION_ATT_STATE = "state"; 96740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String CONDITION_ATT_FLAGS = "flags"; 977c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 98740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String EXIT_CONDITION_TAG = "exitCondition"; 99740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static final String EXIT_CONDITION_ATT_COMPONENT = "component"; 1007c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 1017c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public boolean allowCalls; 102b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public boolean allowMessages; 1037c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public boolean allowEvents = DEFAULT_ALLOW_EVENTS; 104b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public int allowFrom = SOURCE_ANYONE; 105740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 106740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public String sleepMode; 1077c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int sleepStartHour; // 0-23 1087c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int sleepStartMinute; // 0-59 1097c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int sleepEndHour; 110740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public int sleepEndMinute; 111ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose public boolean sleepNone; // false = priority, true = none 1129dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks public ComponentName[] conditionComponents; 1139dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks public Uri[] conditionIds; 1147c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public Condition exitCondition; 115ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose public ComponentName exitConditionComponent; 116740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 117740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public ZenModeConfig() { } 118b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 119b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public ZenModeConfig(Parcel source) { 120b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose allowCalls = source.readInt() == 1; 121740d490593e0de8732a697c9f77b90ddd463863bJordan Rose allowMessages = source.readInt() == 1; 122740d490593e0de8732a697c9f77b90ddd463863bJordan Rose allowEvents = source.readInt() == 1; 123740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (source.readInt() == 1) { 124740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepMode = source.readString(); 125740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 126740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepStartHour = source.readInt(); 1277c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose sleepStartMinute = source.readInt(); 128740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepEndHour = source.readInt(); 129740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepEndMinute = source.readInt(); 130740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepNone = source.readInt() == 1; 131740d490593e0de8732a697c9f77b90ddd463863bJordan Rose int len = source.readInt(); 132740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (len > 0) { 133740d490593e0de8732a697c9f77b90ddd463863bJordan Rose conditionComponents = new ComponentName[len]; 134740d490593e0de8732a697c9f77b90ddd463863bJordan Rose source.readTypedArray(conditionComponents, ComponentName.CREATOR); 135740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 136740d490593e0de8732a697c9f77b90ddd463863bJordan Rose len = source.readInt(); 137740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (len > 0) { 138b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose conditionIds = new Uri[len]; 139740d490593e0de8732a697c9f77b90ddd463863bJordan Rose source.readTypedArray(conditionIds, Uri.CREATOR); 140740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 141740d490593e0de8732a697c9f77b90ddd463863bJordan Rose allowFrom = source.readInt(); 142740d490593e0de8732a697c9f77b90ddd463863bJordan Rose exitCondition = source.readParcelable(null); 143740d490593e0de8732a697c9f77b90ddd463863bJordan Rose exitConditionComponent = source.readParcelable(null); 144740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 145740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 146740d490593e0de8732a697c9f77b90ddd463863bJordan Rose @Override 147740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public void writeToParcel(Parcel dest, int flags) { 148740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(allowCalls ? 1 : 0); 149740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(allowMessages ? 1 : 0); 150de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose dest.writeInt(allowEvents ? 1 : 0); 151de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose if (sleepMode != null) { 1527c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeInt(1); 1537c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeString(sleepMode); 1547c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } else { 155de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose dest.writeInt(0); 156740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 1577c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeInt(sleepStartHour); 158740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(sleepStartMinute); 159740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(sleepEndHour); 160740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(sleepEndMinute); 1617c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeInt(sleepNone ? 1 : 0); 162740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (conditionComponents != null && conditionComponents.length > 0) { 163740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(conditionComponents.length); 1647c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeTypedArray(conditionComponents, 0); 165740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } else { 1667c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeInt(0); 167740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 168740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (conditionIds != null && conditionIds.length > 0) { 169740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeInt(conditionIds.length); 170740d490593e0de8732a697c9f77b90ddd463863bJordan Rose dest.writeTypedArray(conditionIds, 0); 171e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose } else { 172e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose dest.writeInt(0); 1737c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 1747c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeInt(allowFrom); 1757c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose dest.writeParcelable(exitCondition, 0); 176e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose dest.writeParcelable(exitConditionComponent, 0); 177740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 178740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 179740d490593e0de8732a697c9f77b90ddd463863bJordan Rose @Override 18085d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose public String toString() { 18185d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') 18285d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose .append("allowCalls=").append(allowCalls) 18385d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose .append(",allowMessages=").append(allowMessages) 18485d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose .append(",allowFrom=").append(sourceToString(allowFrom)) 1857c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose .append(",allowEvents=").append(allowEvents) 1867c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose .append(",sleepMode=").append(sleepMode) 1877c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute) 18885d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute) 18928038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose .append(",sleepNone=").append(sleepNone) 1908d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose .append(",conditionComponents=") 19128038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose .append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents)) 19228038f33aa2db4833881fea757a1f0daf85ac02bJordan Rose .append(",conditionIds=") 193740d490593e0de8732a697c9f77b90ddd463863bJordan Rose .append(conditionIds == null ? null : TextUtils.join(",", conditionIds)) 194740d490593e0de8732a697c9f77b90ddd463863bJordan Rose .append(",exitCondition=").append(exitCondition) 195740d490593e0de8732a697c9f77b90ddd463863bJordan Rose .append(",exitConditionComponent=").append(exitConditionComponent) 196740d490593e0de8732a697c9f77b90ddd463863bJordan Rose .append(']').toString(); 197740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 198740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 199740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static String sourceToString(int source) { 20085d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose switch (source) { 20185d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose case SOURCE_ANYONE: 2027c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return "anyone"; 2037c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose case SOURCE_CONTACT: 2047c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return "contacts"; 20585d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose case SOURCE_STAR: 20685d7e01cf639b257d70f8a129709a2d7594d7b22Jordan Rose return "stars"; 207e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose default: 208740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return "UNKNOWN"; 209740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 210740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 211740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 212e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose @Override 213e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose public boolean equals(Object o) { 214e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose if (!(o instanceof ZenModeConfig)) return false; 215e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose if (o == this) return true; 216e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose final ZenModeConfig other = (ZenModeConfig) o; 217e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose return other.allowCalls == allowCalls 218e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.allowMessages == allowMessages 219e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.allowFrom == allowFrom 220e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.allowEvents == allowEvents 221e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && Objects.equals(other.sleepMode, sleepMode) 222e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.sleepNone == sleepNone 223e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.sleepStartHour == sleepStartHour 224e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.sleepStartMinute == sleepStartMinute 225e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.sleepEndHour == sleepEndHour 226e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && other.sleepEndMinute == sleepEndMinute 227e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && Objects.deepEquals(other.conditionComponents, conditionComponents) 2287c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose && Objects.deepEquals(other.conditionIds, conditionIds) 229e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && Objects.equals(other.exitCondition, exitCondition) 2307c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose && Objects.equals(other.exitConditionComponent, exitConditionComponent); 231e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose } 232740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 233740d490593e0de8732a697c9f77b90ddd463863bJordan Rose @Override 234740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public int hashCode() { 235e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose return Objects.hash(allowCalls, allowMessages, allowFrom, allowEvents, sleepMode, sleepNone, 236e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute, 237e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds), 238e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose exitCondition, exitConditionComponent); 239e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose } 240740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 241740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public boolean isValid() { 242740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return isValidHour(sleepStartHour) && isValidMinute(sleepStartMinute) 243740d490593e0de8732a697c9f77b90ddd463863bJordan Rose && isValidHour(sleepEndHour) && isValidMinute(sleepEndMinute) 244e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose && isValidSleepMode(sleepMode); 245740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 246740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 247740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static boolean isValidSleepMode(String sleepMode) { 248740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS) 2490ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS) || tryParseDays(sleepMode) != null; 250b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 2510ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose 2520ffbfd1a7f80f9a3c07317cb8f44c562f2ba1ba5Jordan Rose public static int[] tryParseDays(String sleepMode) { 253740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (sleepMode == null) return null; 254740d490593e0de8732a697c9f77b90ddd463863bJordan Rose sleepMode = sleepMode.trim(); 255740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (SLEEP_MODE_NIGHTS.equals(sleepMode)) return ALL_DAYS; 256b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose if (SLEEP_MODE_WEEKNIGHTS.equals(sleepMode)) return WEEKNIGHT_DAYS; 257740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (!sleepMode.startsWith(SLEEP_MODE_DAYS_PREFIX)) return null; 258740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (sleepMode.equals(SLEEP_MODE_DAYS_PREFIX)) return null; 259740d490593e0de8732a697c9f77b90ddd463863bJordan Rose final String[] tokens = sleepMode.substring(SLEEP_MODE_DAYS_PREFIX.length()).split(","); 260740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (tokens.length == 0) return null; 261b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final int[] rt = new int[tokens.length]; 2627c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose for (int i = 0; i < tokens.length; i++) { 2637c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final int day = tryParseInt(tokens[i], -1); 264b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose if (day == -1) return null; 2657c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose rt[i] = day; 2667c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 267740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return rt; 2687c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 269740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 270740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static int tryParseInt(String value, int defValue) { 271b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose if (TextUtils.isEmpty(value)) return defValue; 272b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose try { 2737c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return Integer.valueOf(value); 2747c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } catch (NumberFormatException e) { 275b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose return defValue; 276740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 2777c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 278ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose 279ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose public static ZenModeConfig readXml(XmlPullParser parser) 280ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose throws XmlPullParserException, IOException { 281ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose int type = parser.getEventType(); 282ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose if (type != XmlPullParser.START_TAG) return null; 283ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose String tag = parser.getName(); 284ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose if (!ZEN_TAG.equals(tag)) return null; 2857c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final ZenModeConfig rt = new ZenModeConfig(); 286b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final int version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION); 2877c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final ArrayList<ComponentName> conditionComponents = new ArrayList<ComponentName>(); 2887c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final ArrayList<Uri> conditionIds = new ArrayList<Uri>(); 289b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 290740d490593e0de8732a697c9f77b90ddd463863bJordan Rose tag = parser.getName(); 291740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) { 292740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (!conditionComponents.isEmpty()) { 293740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.conditionComponents = conditionComponents 294740d490593e0de8732a697c9f77b90ddd463863bJordan Rose .toArray(new ComponentName[conditionComponents.size()]); 295740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.conditionIds = conditionIds.toArray(new Uri[conditionIds.size()]); 296740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 297740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return rt; 298740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 299b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose if (type == XmlPullParser.START_TAG) { 3007c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (ALLOW_TAG.equals(tag)) { 3017c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false); 302740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false); 303740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS, DEFAULT_ALLOW_EVENTS); 304740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.allowFrom = safeInt(parser, ALLOW_ATT_FROM, SOURCE_ANYONE); 3057c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) { 306b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom); 307b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 308740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } else if (SLEEP_TAG.equals(tag)) { 3097c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE); 310740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.sleepMode = isValidSleepMode(mode)? mode : null; 3117c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose rt.sleepNone = safeBoolean(parser, SLEEP_ATT_NONE, false); 3127c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0); 3137c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0); 314b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0); 315740d490593e0de8732a697c9f77b90ddd463863bJordan Rose final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0); 316740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.sleepStartHour = isValidHour(startHour) ? startHour : 0; 317740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0; 318740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.sleepEndHour = isValidHour(endHour) ? endHour : 0; 319740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0; 320740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } else if (CONDITION_TAG.equals(tag)) { 321740d490593e0de8732a697c9f77b90ddd463863bJordan Rose final ComponentName component = 322740d490593e0de8732a697c9f77b90ddd463863bJordan Rose safeComponentName(parser, CONDITION_ATT_COMPONENT); 323740d490593e0de8732a697c9f77b90ddd463863bJordan Rose final Uri conditionId = safeUri(parser, CONDITION_ATT_ID); 324740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (component != null && conditionId != null) { 325740d490593e0de8732a697c9f77b90ddd463863bJordan Rose conditionComponents.add(component); 326740d490593e0de8732a697c9f77b90ddd463863bJordan Rose conditionIds.add(conditionId); 327740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 328740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } else if (EXIT_CONDITION_TAG.equals(tag)) { 329740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.exitCondition = readConditionXml(parser); 3307c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (rt.exitCondition != null) { 331740d490593e0de8732a697c9f77b90ddd463863bJordan Rose rt.exitConditionComponent = 3327c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose safeComponentName(parser, EXIT_CONDITION_ATT_COMPONENT); 333b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 334740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 335740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 336740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 337740d490593e0de8732a697c9f77b90ddd463863bJordan Rose throw new IllegalStateException("Failed to reach END_DOCUMENT"); 338740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 339c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose 340c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose public void writeXml(XmlSerializer out) throws IOException { 341c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.startTag(null, ZEN_TAG); 342740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.attribute(null, ZEN_ATT_VERSION, Integer.toString(XML_VERSION)); 3437c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 344740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.startTag(null, ALLOW_TAG); 345c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls)); 3467c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages)); 3477c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents)); 348c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, ALLOW_ATT_FROM, Integer.toString(allowFrom)); 349c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.endTag(null, ALLOW_TAG); 3507c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 351c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.startTag(null, SLEEP_TAG); 352c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose if (sleepMode != null) { 353c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_MODE, sleepMode); 354c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose } 355c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_NONE, Boolean.toString(sleepNone)); 356c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour)); 357c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute)); 358c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour)); 359c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute)); 360c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose out.endTag(null, SLEEP_TAG); 361c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose 362740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (conditionComponents != null && conditionIds != null 363740d490593e0de8732a697c9f77b90ddd463863bJordan Rose && conditionComponents.length == conditionIds.length) { 364c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose for (int i = 0; i < conditionComponents.length; i++) { 3657c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.startTag(null, CONDITION_TAG); 366740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.attribute(null, CONDITION_ATT_COMPONENT, 3677c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose conditionComponents[i].flattenToString()); 368740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.attribute(null, CONDITION_ATT_ID, conditionIds[i].toString()); 369740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.endTag(null, CONDITION_TAG); 370740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 3717c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 3727c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (exitCondition != null && exitConditionComponent != null) { 3737c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.startTag(null, EXIT_CONDITION_TAG); 374e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose out.attribute(null, EXIT_CONDITION_ATT_COMPONENT, 375740d490593e0de8732a697c9f77b90ddd463863bJordan Rose exitConditionComponent.flattenToString()); 376740d490593e0de8732a697c9f77b90ddd463863bJordan Rose writeConditionXml(exitCondition, out); 377740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.endTag(null, EXIT_CONDITION_TAG); 378740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 379740d490593e0de8732a697c9f77b90ddd463863bJordan Rose out.endTag(null, ZEN_TAG); 380fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose } 381fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose 382fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose public static Condition readConditionXml(XmlPullParser parser) { 383fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose final Uri id = safeUri(parser, CONDITION_ATT_ID); 384c36b30c92c78b95fd29fb5d9d6214d737b3bcb02Jordan Rose final String summary = parser.getAttributeValue(null, CONDITION_ATT_SUMMARY); 385fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose final String line1 = parser.getAttributeValue(null, CONDITION_ATT_LINE1); 386fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose final String line2 = parser.getAttributeValue(null, CONDITION_ATT_LINE2); 387fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose final int icon = safeInt(parser, CONDITION_ATT_ICON, -1); 3887c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final int state = safeInt(parser, CONDITION_ATT_STATE, -1); 389fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose final int flags = safeInt(parser, CONDITION_ATT_FLAGS, -1); 3907c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose try { 391fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose return new Condition(id, summary, line1, line2, icon, state, flags); 392fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose } catch (IllegalArgumentException e) { 393fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose Slog.w(TAG, "Unable to read condition xml", e); 3947c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return null; 3957c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 3967c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 3977c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 398fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose public static void writeConditionXml(Condition c, XmlSerializer out) throws IOException { 399fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose out.attribute(null, CONDITION_ATT_ID, c.id.toString()); 400fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose out.attribute(null, CONDITION_ATT_SUMMARY, c.summary); 4017c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.attribute(null, CONDITION_ATT_LINE1, c.line1); 4027c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.attribute(null, CONDITION_ATT_LINE2, c.line2); 4037c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose out.attribute(null, CONDITION_ATT_ICON, Integer.toString(c.icon)); 404e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose out.attribute(null, CONDITION_ATT_STATE, Integer.toString(c.state)); 405fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose out.attribute(null, CONDITION_ATT_FLAGS, Integer.toString(c.flags)); 406fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose } 407fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose 408fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose public static boolean isValidHour(int val) { 409fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose return val >= 0 && val < 24; 410740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 411740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 412fdaa33818cf9bad8d092136e73bd2e489cb821baJordan Rose public static boolean isValidMinute(int val) { 413740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return val >= 0 && val < 60; 414740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 4157c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 416740d490593e0de8732a697c9f77b90ddd463863bJordan Rose private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) { 4177c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final String val = parser.getAttributeValue(null, att); 418740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (TextUtils.isEmpty(val)) return defValue; 419740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return Boolean.valueOf(val); 420740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 421740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 4227c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose private static int safeInt(XmlPullParser parser, String att, int defValue) { 42369f87c956b3ac2b80124fd9604af012e1061473aJordan Rose final String val = parser.getAttributeValue(null, att); 42469f87c956b3ac2b80124fd9604af012e1061473aJordan Rose return tryParseInt(val, defValue); 42569f87c956b3ac2b80124fd9604af012e1061473aJordan Rose } 42669f87c956b3ac2b80124fd9604af012e1061473aJordan Rose 42769f87c956b3ac2b80124fd9604af012e1061473aJordan Rose private static ComponentName safeComponentName(XmlPullParser parser, String att) { 42869f87c956b3ac2b80124fd9604af012e1061473aJordan Rose final String val = parser.getAttributeValue(null, att); 42969f87c956b3ac2b80124fd9604af012e1061473aJordan Rose if (TextUtils.isEmpty(val)) return null; 43069f87c956b3ac2b80124fd9604af012e1061473aJordan Rose return ComponentName.unflattenFromString(val); 43169f87c956b3ac2b80124fd9604af012e1061473aJordan Rose } 43269f87c956b3ac2b80124fd9604af012e1061473aJordan Rose 43369f87c956b3ac2b80124fd9604af012e1061473aJordan Rose private static Uri safeUri(XmlPullParser parser, String att) { 43469f87c956b3ac2b80124fd9604af012e1061473aJordan Rose final String val = parser.getAttributeValue(null, att); 43569f87c956b3ac2b80124fd9604af012e1061473aJordan Rose if (TextUtils.isEmpty(val)) return null; 43669f87c956b3ac2b80124fd9604af012e1061473aJordan Rose return Uri.parse(val); 43769f87c956b3ac2b80124fd9604af012e1061473aJordan Rose } 438740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 439740d490593e0de8732a697c9f77b90ddd463863bJordan Rose @Override 4407c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int describeContents() { 441ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose return 0; 442ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose } 443ee158bc29bc12ce544996f7cdfde14aba63acf4dJordan Rose 4447c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public ZenModeConfig copy() { 4457c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final Parcel parcel = Parcel.obtain(); 446b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose try { 4477c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose writeToParcel(parcel, 0); 448b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose parcel.setDataPosition(0); 449740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return new ZenModeConfig(parcel); 450740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } finally { 451740d490593e0de8732a697c9f77b90ddd463863bJordan Rose parcel.recycle(); 452740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 453740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 454740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 455740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static final Parcelable.Creator<ZenModeConfig> CREATOR 456740d490593e0de8732a697c9f77b90ddd463863bJordan Rose = new Parcelable.Creator<ZenModeConfig>() { 457740d490593e0de8732a697c9f77b90ddd463863bJordan Rose @Override 458740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public ZenModeConfig createFromParcel(Parcel source) { 4597c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return new ZenModeConfig(source); 460740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 461740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 462b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose @Override 463b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public ZenModeConfig[] newArray(int size) { 464740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return new ZenModeConfig[size]; 4657c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 466b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose }; 467b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 468b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public DowntimeInfo toDowntimeInfo() { 469b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final DowntimeInfo downtime = new DowntimeInfo(); 470b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose downtime.startHour = sleepStartHour; 471740d490593e0de8732a697c9f77b90ddd463863bJordan Rose downtime.startMinute = sleepStartMinute; 4727c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose downtime.endHour = sleepEndHour; 473b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose downtime.endMinute = sleepEndMinute; 474b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose downtime.mode = sleepMode; 475740d490593e0de8732a697c9f77b90ddd463863bJordan Rose downtime.none = sleepNone; 4767c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return downtime; 477b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 478b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 479b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static Condition toTimeCondition(Context context, int minutesFromNow, int userHandle) { 4807c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final long now = System.currentTimeMillis(); 481b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final long millis = minutesFromNow == 0 ? ZERO_VALUE_MS : minutesFromNow * MINUTES_MS; 482740d490593e0de8732a697c9f77b90ddd463863bJordan Rose return toTimeCondition(context, now + millis, minutesFromNow, now, userHandle); 483740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 4847c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 485740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public static Condition toTimeCondition(Context context, long time, int minutes, long now, 4867c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose int userHandle) { 487b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final int num, summaryResId, line1ResId; 488740d490593e0de8732a697c9f77b90ddd463863bJordan Rose if (minutes < 60) { 489740d490593e0de8732a697c9f77b90ddd463863bJordan Rose // display as minutes 4907c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose num = minutes; 4917c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose summaryResId = R.plurals.zen_mode_duration_minutes_summary; 4927c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose line1ResId = R.plurals.zen_mode_duration_minutes; 493e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose } else { 494740d490593e0de8732a697c9f77b90ddd463863bJordan Rose // display as hours 495740d490593e0de8732a697c9f77b90ddd463863bJordan Rose num = Math.round(minutes / 60f); 496740d490593e0de8732a697c9f77b90ddd463863bJordan Rose summaryResId = com.android.internal.R.plurals.zen_mode_duration_hours_summary; 497740d490593e0de8732a697c9f77b90ddd463863bJordan Rose line1ResId = com.android.internal.R.plurals.zen_mode_duration_hours; 498740d490593e0de8732a697c9f77b90ddd463863bJordan Rose } 4998d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final String skeleton = DateFormat.is24HourFormat(context, userHandle) ? "Hm" : "hma"; 5008d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton); 5018d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final CharSequence formattedTime = DateFormat.format(pattern, time); 5028d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final Resources res = context.getResources(); 5038d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final String summary = res.getQuantityString(summaryResId, num, num, formattedTime); 5048d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final String line1 = res.getQuantityString(line1ResId, num, num, formattedTime); 5057c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final String line2 = res.getString(R.string.zen_mode_until, formattedTime); 5068d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose final Uri id = toCountdownConditionId(time); 5078d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose return new Condition(id, summary, line1, line2, 0, Condition.STATE_TRUE, 508b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose Condition.FLAG_RELEVANT_NOW); 509b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 510b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 511b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose // For built-in conditions 512b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static final String SYSTEM_AUTHORITY = "android"; 513b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 514b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose // Built-in countdown conditions, e.g. condition://android/countdown/1399917958951 515b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose public static final String COUNTDOWN_PATH = "countdown"; 516b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 5178d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose public static Uri toCountdownConditionId(long time) { 5187c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose return new Uri.Builder().scheme(Condition.SCHEME) 519b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .authority(SYSTEM_AUTHORITY) 520b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .appendPath(COUNTDOWN_PATH) 521b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .appendPath(Long.toString(time)) 5228d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose .build(); 5237c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose } 5247c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose 5257c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static long tryParseCountdownConditionId(Uri conditionId) { 5267c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (!Condition.isValidId(conditionId, SYSTEM_AUTHORITY)) return 0; 5277c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (conditionId.getPathSegments().size() != 2 5288d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose || !COUNTDOWN_PATH.equals(conditionId.getPathSegments().get(0))) return 0; 5297c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose try { 530e54cfc7b9990acffd0a8a4ba381717b4bb9f3011Jordan Rose return Long.parseLong(conditionId.getPathSegments().get(1)); 5318d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose } catch (RuntimeException e) { 5328d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose Slog.w(TAG, "Error parsing countdown condition: " + conditionId, e); 5338d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose return 0; 5348d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose } 5358d276d38c258dfc572586daf6c0e8f8fce249c0eJordan Rose } 5360e020adcb69e91826f4ee14a0c1d381f7b624a34Jordan Rose 5370e020adcb69e91826f4ee14a0c1d381f7b624a34Jordan Rose public static boolean isValidCountdownConditionId(Uri conditionId) { 5380e020adcb69e91826f4ee14a0c1d381f7b624a34Jordan Rose return tryParseCountdownConditionId(conditionId) != 0; 53970cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose } 54070cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose 541b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose // Built-in downtime conditions 54270cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose // e.g. condition://android/downtime?start=10.00&end=7.00&mode=days%3A5%2C6&none=false 5437c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static final String DOWNTIME_PATH = "downtime"; 54470cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose 5457c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static Uri toDowntimeConditionId(DowntimeInfo downtime) { 546b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose return new Uri.Builder().scheme(Condition.SCHEME) 547b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .authority(SYSTEM_AUTHORITY) 548b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .appendPath(DOWNTIME_PATH) 5497c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose .appendQueryParameter("start", downtime.startHour + "." + downtime.startMinute) 550b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose .appendQueryParameter("end", downtime.endHour + "." + downtime.endMinute) 55170cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose .appendQueryParameter("mode", downtime.mode) 55270cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose .appendQueryParameter("none", Boolean.toString(downtime.none)) 5537c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose .build(); 554b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 555b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose 55670cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose public static DowntimeInfo tryParseDowntimeConditionId(Uri conditionId) { 5577c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (!Condition.isValidId(conditionId, SYSTEM_AUTHORITY) 55870cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose || conditionId.getPathSegments().size() != 1 55970cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose || !DOWNTIME_PATH.equals(conditionId.getPathSegments().get(0))) { 56070cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose return null; 561b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 56270cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start")); 56370cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end")); 5647c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose if (start == null || end == null) return null; 565b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose final DowntimeInfo downtime = new DowntimeInfo(); 56670cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose downtime.startHour = start[0]; 56770cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose downtime.startMinute = start[1]; 56870cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose downtime.endHour = end[0]; 56970cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose downtime.endMinute = end[1]; 57070cbf3cc09eb21db1108396d30a414ea66d842ccJordan Rose downtime.mode = conditionId.getQueryParameter("mode"); 5718919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose downtime.none = Boolean.toString(true).equals(conditionId.getQueryParameter("none")); 5728919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose return downtime; 5738919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose } 5748919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose 5758919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose private static int[] tryParseHourAndMinute(String value) { 5768919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose if (TextUtils.isEmpty(value)) return null; 5778919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose final int i = value.indexOf('.'); 5788919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose if (i < 1 || i >= value.length() - 1) return null; 5798919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose final int hour = tryParseInt(value.substring(0, i), -1); 5808919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose final int minute = tryParseInt(value.substring(i + 1), -1); 581cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose return isValidHour(hour) && isValidMinute(minute) ? new int[] { hour, minute } : null; 5828919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose } 5838919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose 584cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose public static boolean isValidDowntimeConditionId(Uri conditionId) { 5858919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose return tryParseDowntimeConditionId(conditionId) != null; 586cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose } 5878919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose 5887c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public static class DowntimeInfo { 589740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public int startHour; // 0-23 5907c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int startMinute; // 0-59 5919dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks public int endHour; 5929dc5167e4017ef4c8b327abb6f72225eec2e0f19Anna Zaks public int endMinute; 593740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public String mode; 594740d490593e0de8732a697c9f77b90ddd463863bJordan Rose public boolean none; 5958919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose 5968919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose @Override 5977c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose public int hashCode() { 5988919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose return 0; 599b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 600de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose 6017c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose @Override 6028919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose public boolean equals(Object o) { 603cde8cdbd6a662c636164465ad309b5f17ff01064Jordan Rose if (!(o instanceof DowntimeInfo)) return false; 6047c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose final DowntimeInfo other = (DowntimeInfo) o; 605b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose return startHour == other.startHour 606b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose && startMinute == other.startMinute 6077c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose && endHour == other.endHour 608b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose && endMinute == other.endMinute 609b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose && Objects.equals(mode, other.mode) 6107c99aa385178c630e29f671299cdd9c104f1c885Jordan Rose && none == other.none; 611b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 612b7a23e05d1d8f07f2a6edce5c88c728fe894c2c7Jordan Rose } 613740d490593e0de8732a697c9f77b90ddd463863bJordan Rose 6148919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose // built-in next alarm conditions 6158919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose public static final String NEXT_ALARM_PATH = "next_alarm"; 6168919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose} 6178919e688dc610d1f632a4d43f7f1489f67255476Jordan Rose