ZenModeConfig.java revision 3b98b3f1f85aff0c84ebef4dd497c146d1b4d248
1/** 2 * Copyright (c) 2014, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.service.notification; 18 19import android.content.ComponentName; 20import android.net.Uri; 21import android.os.Parcel; 22import android.os.Parcelable; 23import android.text.TextUtils; 24 25import org.xmlpull.v1.XmlPullParser; 26import org.xmlpull.v1.XmlPullParserException; 27import org.xmlpull.v1.XmlSerializer; 28 29import java.io.IOException; 30import java.util.ArrayList; 31import java.util.Arrays; 32import java.util.Objects; 33 34/** 35 * Persisted configuration for zen mode. 36 * 37 * @hide 38 */ 39public class ZenModeConfig implements Parcelable { 40 41 public static final String SLEEP_MODE_NIGHTS = "nights"; 42 public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights"; 43 44 private static final int XML_VERSION = 1; 45 private static final String ZEN_TAG = "zen"; 46 private static final String ZEN_ATT_VERSION = "version"; 47 private static final String ALLOW_TAG = "allow"; 48 private static final String ALLOW_ATT_CALLS = "calls"; 49 private static final String ALLOW_ATT_MESSAGES = "messages"; 50 private static final String SLEEP_TAG = "sleep"; 51 private static final String SLEEP_ATT_MODE = "mode"; 52 53 private static final String SLEEP_ATT_START_HR = "startHour"; 54 private static final String SLEEP_ATT_START_MIN = "startMin"; 55 private static final String SLEEP_ATT_END_HR = "endHour"; 56 private static final String SLEEP_ATT_END_MIN = "endMin"; 57 58 private static final String CONDITION_TAG = "condition"; 59 private static final String CONDITION_ATT_COMPONENT = "component"; 60 private static final String CONDITION_ATT_ID = "id"; 61 62 public boolean allowCalls; 63 public boolean allowMessages; 64 65 public String sleepMode; 66 public int sleepStartHour; 67 public int sleepStartMinute; 68 public int sleepEndHour; 69 public int sleepEndMinute; 70 public ComponentName[] conditionComponents; 71 public Uri[] conditionIds; 72 73 public ZenModeConfig() { } 74 75 public ZenModeConfig(Parcel source) { 76 allowCalls = source.readInt() == 1; 77 allowMessages = source.readInt() == 1; 78 if (source.readInt() == 1) { 79 sleepMode = source.readString(); 80 } 81 sleepStartHour = source.readInt(); 82 sleepStartMinute = source.readInt(); 83 sleepEndHour = source.readInt(); 84 sleepEndMinute = source.readInt(); 85 int len = source.readInt(); 86 if (len > 0) { 87 conditionComponents = new ComponentName[len]; 88 source.readTypedArray(conditionComponents, ComponentName.CREATOR); 89 } 90 len = source.readInt(); 91 if (len > 0) { 92 conditionIds = new Uri[len]; 93 source.readTypedArray(conditionIds, Uri.CREATOR); 94 } 95 } 96 97 @Override 98 public void writeToParcel(Parcel dest, int flags) { 99 dest.writeInt(allowCalls ? 1 : 0); 100 dest.writeInt(allowMessages ? 1 : 0); 101 if (sleepMode != null) { 102 dest.writeInt(1); 103 dest.writeString(sleepMode); 104 } else { 105 dest.writeInt(0); 106 } 107 dest.writeInt(sleepStartHour); 108 dest.writeInt(sleepStartMinute); 109 dest.writeInt(sleepEndHour); 110 dest.writeInt(sleepEndMinute); 111 if (conditionComponents != null && conditionComponents.length > 0) { 112 dest.writeInt(conditionComponents.length); 113 dest.writeTypedArray(conditionComponents, 0); 114 } else { 115 dest.writeInt(0); 116 } 117 if (conditionIds != null && conditionIds.length > 0) { 118 dest.writeInt(conditionIds.length); 119 dest.writeTypedArray(conditionIds, 0); 120 } else { 121 dest.writeInt(0); 122 } 123 } 124 125 @Override 126 public String toString() { 127 return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[') 128 .append("allowCalls=").append(allowCalls) 129 .append(",allowMessages=").append(allowMessages) 130 .append(",sleepMode=").append(sleepMode) 131 .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute) 132 .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute) 133 .append(",conditionComponents=") 134 .append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents)) 135 .append(",conditionIds=") 136 .append(conditionIds == null ? null : TextUtils.join(",", conditionIds)) 137 .append(']').toString(); 138 } 139 140 @Override 141 public boolean equals(Object o) { 142 if (!(o instanceof ZenModeConfig)) return false; 143 if (o == this) return true; 144 final ZenModeConfig other = (ZenModeConfig) o; 145 return other.allowCalls == allowCalls 146 && other.allowMessages == allowMessages 147 && Objects.equals(other.sleepMode, sleepMode) 148 && other.sleepStartHour == sleepStartHour 149 && other.sleepStartMinute == sleepStartMinute 150 && other.sleepEndHour == sleepEndHour 151 && other.sleepEndMinute == sleepEndMinute 152 && Objects.deepEquals(other.conditionComponents, conditionComponents) 153 && Objects.deepEquals(other.conditionIds, conditionIds); 154 } 155 156 @Override 157 public int hashCode() { 158 return Objects.hash(allowCalls, allowMessages, sleepMode, sleepStartHour, 159 sleepStartMinute, sleepEndHour, sleepEndMinute, 160 Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds)); 161 } 162 163 public boolean isValid() { 164 return isValidHour(sleepStartHour) && isValidMinute(sleepStartMinute) 165 && isValidHour(sleepEndHour) && isValidMinute(sleepEndMinute) 166 && (sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS) 167 || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS)); 168 } 169 170 public static ZenModeConfig readXml(XmlPullParser parser) 171 throws XmlPullParserException, IOException { 172 int type = parser.getEventType(); 173 if (type != XmlPullParser.START_TAG) return null; 174 String tag = parser.getName(); 175 if (!ZEN_TAG.equals(tag)) return null; 176 final ZenModeConfig rt = new ZenModeConfig(); 177 final int version = Integer.parseInt(parser.getAttributeValue(null, ZEN_ATT_VERSION)); 178 final ArrayList<ComponentName> conditionComponents = new ArrayList<ComponentName>(); 179 final ArrayList<Uri> conditionIds = new ArrayList<Uri>(); 180 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 181 tag = parser.getName(); 182 if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) { 183 if (!conditionComponents.isEmpty()) { 184 rt.conditionComponents = conditionComponents 185 .toArray(new ComponentName[conditionComponents.size()]); 186 rt.conditionIds = conditionIds.toArray(new Uri[conditionIds.size()]); 187 } 188 return rt; 189 } 190 if (type == XmlPullParser.START_TAG) { 191 if (ALLOW_TAG.equals(tag)) { 192 rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false); 193 rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false); 194 } else if (SLEEP_TAG.equals(tag)) { 195 final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE); 196 rt.sleepMode = (SLEEP_MODE_NIGHTS.equals(mode) 197 || SLEEP_MODE_WEEKNIGHTS.equals(mode)) ? mode : null; 198 final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0); 199 final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0); 200 final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0); 201 final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0); 202 rt.sleepStartHour = isValidHour(startHour) ? startHour : 0; 203 rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0; 204 rt.sleepEndHour = isValidHour(endHour) ? endHour : 0; 205 rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0; 206 } else if (CONDITION_TAG.equals(tag)) { 207 final ComponentName component = 208 safeComponentName(parser, CONDITION_ATT_COMPONENT); 209 final Uri conditionId = safeUri(parser, CONDITION_ATT_ID); 210 if (component != null && conditionId != null) { 211 conditionComponents.add(component); 212 conditionIds.add(conditionId); 213 } 214 } 215 } 216 } 217 throw new IllegalStateException("Failed to reach END_DOCUMENT"); 218 } 219 220 public void writeXml(XmlSerializer out) throws IOException { 221 out.startTag(null, ZEN_TAG); 222 out.attribute(null, ZEN_ATT_VERSION, Integer.toString(XML_VERSION)); 223 224 out.startTag(null, ALLOW_TAG); 225 out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls)); 226 out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages)); 227 out.endTag(null, ALLOW_TAG); 228 229 out.startTag(null, SLEEP_TAG); 230 if (sleepMode != null) { 231 out.attribute(null, SLEEP_ATT_MODE, sleepMode); 232 } 233 out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour)); 234 out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute)); 235 out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour)); 236 out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute)); 237 out.endTag(null, SLEEP_TAG); 238 239 if (conditionComponents != null && conditionIds != null 240 && conditionComponents.length == conditionIds.length) { 241 for (int i = 0; i < conditionComponents.length; i++) { 242 out.startTag(null, CONDITION_TAG); 243 out.attribute(null, CONDITION_ATT_COMPONENT, 244 conditionComponents[i].flattenToString()); 245 out.attribute(null, CONDITION_ATT_ID, conditionIds[i].toString()); 246 out.endTag(null, CONDITION_TAG); 247 } 248 } 249 out.endTag(null, ZEN_TAG); 250 } 251 252 public static boolean isValidHour(int val) { 253 return val >= 0 && val < 24; 254 } 255 256 public static boolean isValidMinute(int val) { 257 return val >= 0 && val < 60; 258 } 259 260 private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) { 261 final String val = parser.getAttributeValue(null, att); 262 if (TextUtils.isEmpty(val)) return defValue; 263 return Boolean.valueOf(val); 264 } 265 266 private static int safeInt(XmlPullParser parser, String att, int defValue) { 267 final String val = parser.getAttributeValue(null, att); 268 if (TextUtils.isEmpty(val)) return defValue; 269 return Integer.valueOf(val); 270 } 271 272 private static ComponentName safeComponentName(XmlPullParser parser, String att) { 273 final String val = parser.getAttributeValue(null, att); 274 if (TextUtils.isEmpty(val)) return null; 275 return ComponentName.unflattenFromString(val); 276 } 277 278 private static Uri safeUri(XmlPullParser parser, String att) { 279 final String val = parser.getAttributeValue(null, att); 280 if (TextUtils.isEmpty(val)) return null; 281 return Uri.parse(val); 282 } 283 284 @Override 285 public int describeContents() { 286 return 0; 287 } 288 289 public ZenModeConfig copy() { 290 final Parcel parcel = Parcel.obtain(); 291 try { 292 writeToParcel(parcel, 0); 293 parcel.setDataPosition(0); 294 return new ZenModeConfig(parcel); 295 } finally { 296 parcel.recycle(); 297 } 298 } 299 300 public static final Parcelable.Creator<ZenModeConfig> CREATOR 301 = new Parcelable.Creator<ZenModeConfig>() { 302 @Override 303 public ZenModeConfig createFromParcel(Parcel source) { 304 return new ZenModeConfig(source); 305 } 306 307 @Override 308 public ZenModeConfig[] newArray(int size) { 309 return new ZenModeConfig[size]; 310 } 311 }; 312} 313