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 17 package android.service.notification; 18 19 import android.annotation.IntDef; 20 import android.annotation.SystemApi; 21 import android.content.Context; 22 import android.net.Uri; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.util.proto.ProtoOutputStream; 26 27 import java.lang.annotation.Retention; 28 import java.lang.annotation.RetentionPolicy; 29 import java.util.Objects; 30 31 /** 32 * The current condition of an {@link android.app.AutomaticZenRule}, provided by the 33 * {@link ConditionProviderService} that owns the rule. Used to tell the system to enter Do Not 34 * Disturb mode and request that the system exit Do Not Disturb mode. 35 */ 36 public final class Condition implements Parcelable { 37 38 @SystemApi 39 public static final String SCHEME = "condition"; 40 41 /** @hide */ 42 @IntDef(prefix = { "STATE_" }, value = { 43 STATE_FALSE, 44 STATE_TRUE, 45 STATE_UNKNOWN, 46 STATE_ERROR 47 }) 48 @Retention(RetentionPolicy.SOURCE) 49 public @interface State {} 50 51 /** 52 * Indicates that Do Not Disturb should be turned off. Note that all Conditions from all 53 * {@link ConditionProviderService} providers must be off for Do Not Disturb to be turned off on 54 * the device. 55 */ 56 public static final int STATE_FALSE = 0; 57 /** 58 * Indicates that Do Not Disturb should be turned on. 59 */ 60 public static final int STATE_TRUE = 1; 61 62 @SystemApi 63 public static final int STATE_UNKNOWN = 2; 64 @SystemApi 65 public static final int STATE_ERROR = 3; 66 67 @SystemApi 68 public static final int FLAG_RELEVANT_NOW = 1 << 0; 69 @SystemApi 70 public static final int FLAG_RELEVANT_ALWAYS = 1 << 1; 71 72 /** 73 * The URI representing the rule being updated. 74 * See {@link android.app.AutomaticZenRule#getConditionId()}. 75 */ 76 public final Uri id; 77 78 /** 79 * A summary of what the rule encoded in {@link #id} means when it is enabled. User visible 80 * if the state of the condition is {@link #STATE_TRUE}. 81 */ 82 public final String summary; 83 84 @SystemApi 85 public final String line1; 86 @SystemApi 87 public final String line2; 88 89 /** 90 * The state of this condition. {@link #STATE_TRUE} will enable Do Not Disturb mode. 91 * {@link #STATE_FALSE} will turn Do Not Disturb off for this rule. Note that Do Not Disturb 92 * might still be enabled globally if other conditions are in a {@link #STATE_TRUE} state. 93 */ 94 @State 95 public final int state; 96 97 @SystemApi 98 public final int flags; 99 @SystemApi 100 public final int icon; 101 102 /** 103 * An object representing the current state of a {@link android.app.AutomaticZenRule}. 104 * @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule 105 * @param summary a user visible description of the rule state. 106 */ 107 public Condition(Uri id, String summary, int state) { 108 this(id, summary, "", "", -1, state, FLAG_RELEVANT_ALWAYS); 109 } 110 111 @SystemApi 112 public Condition(Uri id, String summary, String line1, String line2, int icon, 113 int state, int flags) { 114 if (id == null) throw new IllegalArgumentException("id is required"); 115 if (summary == null) throw new IllegalArgumentException("summary is required"); 116 if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state); 117 this.id = id; 118 this.summary = summary; 119 this.line1 = line1; 120 this.line2 = line2; 121 this.icon = icon; 122 this.state = state; 123 this.flags = flags; 124 } 125 126 public Condition(Parcel source) { 127 this((Uri)source.readParcelable(Condition.class.getClassLoader()), 128 source.readString(), 129 source.readString(), 130 source.readString(), 131 source.readInt(), 132 source.readInt(), 133 source.readInt()); 134 } 135 136 private static boolean isValidState(int state) { 137 return state >= STATE_FALSE && state <= STATE_ERROR; 138 } 139 140 @Override 141 public void writeToParcel(Parcel dest, int flags) { 142 dest.writeParcelable(id, 0); 143 dest.writeString(summary); 144 dest.writeString(line1); 145 dest.writeString(line2); 146 dest.writeInt(icon); 147 dest.writeInt(state); 148 dest.writeInt(this.flags); 149 } 150 151 @Override 152 public String toString() { 153 return new StringBuilder(Condition.class.getSimpleName()).append('[') 154 .append("id=").append(id) 155 .append(",summary=").append(summary) 156 .append(",line1=").append(line1) 157 .append(",line2=").append(line2) 158 .append(",icon=").append(icon) 159 .append(",state=").append(stateToString(state)) 160 .append(",flags=").append(flags) 161 .append(']').toString(); 162 } 163 164 /** @hide */ 165 public void writeToProto(ProtoOutputStream proto, long fieldId) { 166 final long token = proto.start(fieldId); 167 168 // id is guarantreed not to be null. 169 proto.write(ConditionProto.ID, id.toString()); 170 proto.write(ConditionProto.SUMMARY, summary); 171 proto.write(ConditionProto.LINE_1, line1); 172 proto.write(ConditionProto.LINE_2, line2); 173 proto.write(ConditionProto.ICON, icon); 174 proto.write(ConditionProto.STATE, state); 175 proto.write(ConditionProto.FLAGS, flags); 176 177 proto.end(token); 178 } 179 180 @SystemApi 181 public static String stateToString(int state) { 182 if (state == STATE_FALSE) return "STATE_FALSE"; 183 if (state == STATE_TRUE) return "STATE_TRUE"; 184 if (state == STATE_UNKNOWN) return "STATE_UNKNOWN"; 185 if (state == STATE_ERROR) return "STATE_ERROR"; 186 throw new IllegalArgumentException("state is invalid: " + state); 187 } 188 189 @SystemApi 190 public static String relevanceToString(int flags) { 191 final boolean now = (flags & FLAG_RELEVANT_NOW) != 0; 192 final boolean always = (flags & FLAG_RELEVANT_ALWAYS) != 0; 193 if (!now && !always) return "NONE"; 194 if (now && always) return "NOW, ALWAYS"; 195 return now ? "NOW" : "ALWAYS"; 196 } 197 198 @Override 199 public boolean equals(Object o) { 200 if (!(o instanceof Condition)) return false; 201 if (o == this) return true; 202 final Condition other = (Condition) o; 203 return Objects.equals(other.id, id) 204 && Objects.equals(other.summary, summary) 205 && Objects.equals(other.line1, line1) 206 && Objects.equals(other.line2, line2) 207 && other.icon == icon 208 && other.state == state 209 && other.flags == flags; 210 } 211 212 @Override 213 public int hashCode() { 214 return Objects.hash(id, summary, line1, line2, icon, state, flags); 215 } 216 217 @Override 218 public int describeContents() { 219 return 0; 220 } 221 222 @SystemApi 223 public Condition copy() { 224 final Parcel parcel = Parcel.obtain(); 225 try { 226 writeToParcel(parcel, 0); 227 parcel.setDataPosition(0); 228 return new Condition(parcel); 229 } finally { 230 parcel.recycle(); 231 } 232 } 233 234 @SystemApi 235 public static Uri.Builder newId(Context context) { 236 return new Uri.Builder() 237 .scheme(Condition.SCHEME) 238 .authority(context.getPackageName()); 239 } 240 241 @SystemApi 242 public static boolean isValidId(Uri id, String pkg) { 243 return id != null && SCHEME.equals(id.getScheme()) && pkg.equals(id.getAuthority()); 244 } 245 246 public static final Parcelable.Creator<Condition> CREATOR 247 = new Parcelable.Creator<Condition>() { 248 @Override 249 public Condition createFromParcel(Parcel source) { 250 return new Condition(source); 251 } 252 253 @Override 254 public Condition[] newArray(int size) { 255 return new Condition[size]; 256 } 257 }; 258 } 259