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