blob: 34cd9f029746413581aa97ee986ddaa6c307e819 [file] [log] [blame]
Julia Reynolds59e152e2017-01-25 17:42:53 -05001/*
2 * Copyright (C) 2017 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 */
16package android.app;
17
18import android.annotation.SystemApi;
Julia Reynolds005c8b92017-08-24 10:35:53 -040019import android.annotation.TestApi;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010020import android.annotation.UnsupportedAppUsage;
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040021import android.content.Intent;
Julia Reynolds59e152e2017-01-25 17:42:53 -050022import android.os.Parcel;
23import android.os.Parcelable;
Julia Reynolds59e152e2017-01-25 17:42:53 -050024import android.text.TextUtils;
Kweku Adams62b42242017-09-25 12:54:02 -070025import android.util.proto.ProtoOutputStream;
Julia Reynolds59e152e2017-01-25 17:42:53 -050026
27import org.json.JSONException;
28import org.json.JSONObject;
Julia Reynolds005c8b92017-08-24 10:35:53 -040029import org.xmlpull.v1.XmlPullParser;
Julia Reynolds59e152e2017-01-25 17:42:53 -050030import org.xmlpull.v1.XmlSerializer;
31
32import java.io.IOException;
33import java.util.ArrayList;
Julia Reynolds59e152e2017-01-25 17:42:53 -050034import java.util.List;
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -040035import java.util.Objects;
Julia Reynolds59e152e2017-01-25 17:42:53 -050036
37/**
38 * A grouping of related notification channels. e.g., channels that all belong to a single account.
39 */
40public final class NotificationChannelGroup implements Parcelable {
41
Julia Reynolds2c891c92017-03-17 14:23:47 -040042 /**
43 * The maximum length for text fields in a NotificationChannelGroup. Fields will be truncated at
44 * this limit.
45 */
46 private static final int MAX_TEXT_LENGTH = 1000;
47
Julia Reynolds59e152e2017-01-25 17:42:53 -050048 private static final String TAG_GROUP = "channelGroup";
49 private static final String ATT_NAME = "name";
Julia Reynolds005c8b92017-08-24 10:35:53 -040050 private static final String ATT_DESC = "desc";
Julia Reynolds59e152e2017-01-25 17:42:53 -050051 private static final String ATT_ID = "id";
Julia Reynolds005c8b92017-08-24 10:35:53 -040052 private static final String ATT_BLOCKED = "blocked";
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -040053 private static final String ATT_USER_LOCKED = "locked";
Julia Reynolds59e152e2017-01-25 17:42:53 -050054
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -040055 /**
56 * @hide
57 */
58 public static final int USER_LOCKED_BLOCKED_STATE = 0x00000001;
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -040059
60 /**
61 * @see #getId()
62 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +010063 @UnsupportedAppUsage
Julia Reynolds59e152e2017-01-25 17:42:53 -050064 private final String mId;
65 private CharSequence mName;
Julia Reynolds005c8b92017-08-24 10:35:53 -040066 private String mDescription;
67 private boolean mBlocked;
Julia Reynolds59e152e2017-01-25 17:42:53 -050068 private List<NotificationChannel> mChannels = new ArrayList<>();
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -040069 // Bitwise representation of fields that have been changed by the user
70 private int mUserLockedFields;
Julia Reynolds59e152e2017-01-25 17:42:53 -050071
72 /**
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040073 * Creates a notification channel group.
Julia Reynolds59e152e2017-01-25 17:42:53 -050074 *
Julia Reynolds2c891c92017-03-17 14:23:47 -040075 * @param id The id of the group. Must be unique per package. the value may be truncated if
76 * it is too long.
Julia Reynolds1d97e6a2017-03-13 15:05:40 -040077 * @param name The user visible name of the group. You can rename this group when the system
78 * locale changes by listening for the {@link Intent#ACTION_LOCALE_CHANGED}
Julia Reynolds2c891c92017-03-17 14:23:47 -040079 * broadcast. <p>The recommended maximum length is 40 characters; the value may be
80 * truncated if it is too long.
Julia Reynolds59e152e2017-01-25 17:42:53 -050081 */
82 public NotificationChannelGroup(String id, CharSequence name) {
Julia Reynolds2c891c92017-03-17 14:23:47 -040083 this.mId = getTrimmedString(id);
84 this.mName = name != null ? getTrimmedString(name.toString()) : null;
Julia Reynolds59e152e2017-01-25 17:42:53 -050085 }
86
Julia Reynoldsbad42972017-04-25 13:52:49 -040087 /**
88 * @hide
89 */
Julia Reynolds59e152e2017-01-25 17:42:53 -050090 protected NotificationChannelGroup(Parcel in) {
91 if (in.readByte() != 0) {
92 mId = in.readString();
93 } else {
94 mId = null;
95 }
96 mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
Julia Reynolds005c8b92017-08-24 10:35:53 -040097 if (in.readByte() != 0) {
98 mDescription = in.readString();
99 } else {
100 mDescription = null;
101 }
Julia Reynoldsf02562a2017-01-26 13:33:56 -0500102 in.readParcelableList(mChannels, NotificationChannel.class.getClassLoader());
Julia Reynolds005c8b92017-08-24 10:35:53 -0400103 mBlocked = in.readBoolean();
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400104 mUserLockedFields = in.readInt();
Julia Reynolds59e152e2017-01-25 17:42:53 -0500105 }
106
Julia Reynolds2c891c92017-03-17 14:23:47 -0400107 private String getTrimmedString(String input) {
108 if (input != null && input.length() > MAX_TEXT_LENGTH) {
109 return input.substring(0, MAX_TEXT_LENGTH);
110 }
111 return input;
112 }
113
Julia Reynolds59e152e2017-01-25 17:42:53 -0500114 @Override
115 public void writeToParcel(Parcel dest, int flags) {
116 if (mId != null) {
117 dest.writeByte((byte) 1);
118 dest.writeString(mId);
119 } else {
120 dest.writeByte((byte) 0);
121 }
122 TextUtils.writeToParcel(mName, dest, flags);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400123 if (mDescription != null) {
124 dest.writeByte((byte) 1);
125 dest.writeString(mDescription);
126 } else {
127 dest.writeByte((byte) 0);
128 }
Julia Reynolds59e152e2017-01-25 17:42:53 -0500129 dest.writeParcelableList(mChannels, flags);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400130 dest.writeBoolean(mBlocked);
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400131 dest.writeInt(mUserLockedFields);
Julia Reynolds59e152e2017-01-25 17:42:53 -0500132 }
133
134 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400135 * Returns the id of this group.
Julia Reynolds59e152e2017-01-25 17:42:53 -0500136 */
137 public String getId() {
138 return mId;
139 }
140
141 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400142 * Returns the user visible name of this group.
Julia Reynolds59e152e2017-01-25 17:42:53 -0500143 */
144 public CharSequence getName() {
145 return mName;
146 }
147
Julia Reynolds399d9bf2017-08-11 12:52:14 -0400148 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400149 * Returns the user visible description of this group.
150 */
151 public String getDescription() {
152 return mDescription;
153 }
154
155 /**
Julia Reynolds59e152e2017-01-25 17:42:53 -0500156 * Returns the list of channels that belong to this group
Julia Reynolds59e152e2017-01-25 17:42:53 -0500157 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500158 public List<NotificationChannel> getChannels() {
159 return mChannels;
160 }
161
162 /**
Julia Reynolds005c8b92017-08-24 10:35:53 -0400163 * Returns whether or not notifications posted to {@link NotificationChannel channels} belonging
Julia Reynolds8d2b0532018-03-29 15:44:13 -0400164 * to this group are blocked. This value is independent of
165 * {@link NotificationManager#areNotificationsEnabled()} and
166 * {@link NotificationChannel#getImportance()}.
Julia Reynolds005c8b92017-08-24 10:35:53 -0400167 */
168 public boolean isBlocked() {
169 return mBlocked;
170 }
171
172 /**
173 * Sets the user visible description of this group.
174 *
175 * <p>The recommended maximum length is 300 characters; the value may be truncated if it is too
176 * long.
177 */
178 public void setDescription(String description) {
179 mDescription = getTrimmedString(description);
180 }
181
182 /**
183 * @hide
184 */
185 @TestApi
186 public void setBlocked(boolean blocked) {
187 mBlocked = blocked;
188 }
189
190 /**
Julia Reynolds59e152e2017-01-25 17:42:53 -0500191 * @hide
192 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500193 public void addChannel(NotificationChannel channel) {
194 mChannels.add(channel);
195 }
196
197 /**
198 * @hide
199 */
Julia Reynolds005c8b92017-08-24 10:35:53 -0400200 public void setChannels(List<NotificationChannel> channels) {
201 mChannels = channels;
202 }
203
204 /**
205 * @hide
206 */
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400207 @TestApi
208 public void lockFields(int field) {
209 mUserLockedFields |= field;
210 }
211
212 /**
213 * @hide
214 */
215 public void unlockFields(int field) {
216 mUserLockedFields &= ~field;
217 }
218
219 /**
220 * @hide
221 */
222 @TestApi
223 public int getUserLockedFields() {
224 return mUserLockedFields;
225 }
226
227 /**
228 * @hide
229 */
Julia Reynolds005c8b92017-08-24 10:35:53 -0400230 public void populateFromXml(XmlPullParser parser) {
231 // Name, id, and importance are set in the constructor.
232 setDescription(parser.getAttributeValue(null, ATT_DESC));
233 setBlocked(safeBool(parser, ATT_BLOCKED, false));
234 }
235
236 private static boolean safeBool(XmlPullParser parser, String att, boolean defValue) {
237 final String value = parser.getAttributeValue(null, att);
238 if (TextUtils.isEmpty(value)) return defValue;
239 return Boolean.parseBoolean(value);
240 }
241
242 /**
243 * @hide
244 */
Julia Reynolds59e152e2017-01-25 17:42:53 -0500245 public void writeXml(XmlSerializer out) throws IOException {
246 out.startTag(null, TAG_GROUP);
247
248 out.attribute(null, ATT_ID, getId());
Julia Reynoldsd5286842017-03-02 15:37:10 -0500249 if (getName() != null) {
250 out.attribute(null, ATT_NAME, getName().toString());
251 }
Julia Reynolds005c8b92017-08-24 10:35:53 -0400252 if (getDescription() != null) {
253 out.attribute(null, ATT_DESC, getDescription().toString());
254 }
255 out.attribute(null, ATT_BLOCKED, Boolean.toString(isBlocked()));
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400256 out.attribute(null, ATT_USER_LOCKED, Integer.toString(mUserLockedFields));
Julia Reynolds59e152e2017-01-25 17:42:53 -0500257
258 out.endTag(null, TAG_GROUP);
259 }
260
261 /**
262 * @hide
263 */
264 @SystemApi
265 public JSONObject toJson() throws JSONException {
266 JSONObject record = new JSONObject();
267 record.put(ATT_ID, getId());
268 record.put(ATT_NAME, getName());
Julia Reynolds005c8b92017-08-24 10:35:53 -0400269 record.put(ATT_DESC, getDescription());
270 record.put(ATT_BLOCKED, isBlocked());
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400271 record.put(ATT_USER_LOCKED, mUserLockedFields);
Julia Reynolds59e152e2017-01-25 17:42:53 -0500272 return record;
273 }
274
275 public static final Creator<NotificationChannelGroup> CREATOR =
276 new Creator<NotificationChannelGroup>() {
277 @Override
278 public NotificationChannelGroup createFromParcel(Parcel in) {
279 return new NotificationChannelGroup(in);
280 }
281
282 @Override
283 public NotificationChannelGroup[] newArray(int size) {
284 return new NotificationChannelGroup[size];
285 }
286 };
287
288 @Override
289 public int describeContents() {
290 return 0;
291 }
292
293 @Override
294 public boolean equals(Object o) {
295 if (this == o) return true;
296 if (o == null || getClass() != o.getClass()) return false;
Julia Reynolds59e152e2017-01-25 17:42:53 -0500297 NotificationChannelGroup that = (NotificationChannelGroup) o;
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400298 return isBlocked() == that.isBlocked() &&
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400299 mUserLockedFields == that.mUserLockedFields &&
300 Objects.equals(getId(), that.getId()) &&
301 Objects.equals(getName(), that.getName()) &&
302 Objects.equals(getDescription(), that.getDescription()) &&
303 Objects.equals(getChannels(), that.getChannels());
Julia Reynolds74856c42017-02-08 14:47:23 -0500304 }
305
306 @Override
Julia Reynolds59e152e2017-01-25 17:42:53 -0500307 public int hashCode() {
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400308 return Objects.hash(getId(), getName(), getDescription(), isBlocked(), getChannels(),
Julia Reynolds33ab8a02018-12-17 16:19:52 -0500309 mUserLockedFields);
Julia Reynolds59e152e2017-01-25 17:42:53 -0500310 }
311
312 @Override
Julia Reynolds005c8b92017-08-24 10:35:53 -0400313 public NotificationChannelGroup clone() {
314 NotificationChannelGroup cloned = new NotificationChannelGroup(getId(), getName());
315 cloned.setDescription(getDescription());
316 cloned.setBlocked(isBlocked());
317 cloned.setChannels(getChannels());
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400318 cloned.lockFields(mUserLockedFields);
Julia Reynolds005c8b92017-08-24 10:35:53 -0400319 return cloned;
320 }
321
322 @Override
Julia Reynolds59e152e2017-01-25 17:42:53 -0500323 public String toString() {
Julia Reynolds005c8b92017-08-24 10:35:53 -0400324 return "NotificationChannelGroup{"
325 + "mId='" + mId + '\''
326 + ", mName=" + mName
327 + ", mDescription=" + (!TextUtils.isEmpty(mDescription) ? "hasDescription " : "")
328 + ", mBlocked=" + mBlocked
329 + ", mChannels=" + mChannels
Julia Reynoldsb6bd93d2018-10-24 09:22:38 -0400330 + ", mUserLockedFields=" + mUserLockedFields
Julia Reynolds005c8b92017-08-24 10:35:53 -0400331 + '}';
Julia Reynolds59e152e2017-01-25 17:42:53 -0500332 }
Kweku Adams62b42242017-09-25 12:54:02 -0700333
334 /** @hide */
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800335 public void writeToProto(ProtoOutputStream proto, long fieldId) {
336 final long token = proto.start(fieldId);
337
Kweku Adams62b42242017-09-25 12:54:02 -0700338 proto.write(NotificationChannelGroupProto.ID, mId);
339 proto.write(NotificationChannelGroupProto.NAME, mName.toString());
340 proto.write(NotificationChannelGroupProto.DESCRIPTION, mDescription);
341 proto.write(NotificationChannelGroupProto.IS_BLOCKED, mBlocked);
342 for (NotificationChannel channel : mChannels) {
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800343 channel.writeToProto(proto, NotificationChannelGroupProto.CHANNELS);
Kweku Adams62b42242017-09-25 12:54:02 -0700344 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800345 proto.end(token);
Kweku Adams62b42242017-09-25 12:54:02 -0700346 }
Julia Reynolds59e152e2017-01-25 17:42:53 -0500347}