blob: d1aec048bdf15bc3f578949fb2ca7447a283f209 [file] [log] [blame]
Jason Monkd9edfa942017-09-25 12:38:53 -04001/*
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 */
16
Jason Monkd18651f2017-10-05 14:18:49 -040017package android.app.slice;
Jason Monkd9edfa942017-09-25 12:38:53 -040018
19import android.annotation.NonNull;
Jason Monkd18651f2017-10-05 14:18:49 -040020import android.annotation.Nullable;
Jason Monkd9edfa942017-09-25 12:38:53 -040021import android.annotation.StringDef;
22import android.app.PendingIntent;
23import android.app.RemoteInput;
24import android.graphics.drawable.Icon;
25import android.net.Uri;
Jason Monkd18651f2017-10-05 14:18:49 -040026import android.os.Bundle;
Jason Monkd9edfa942017-09-25 12:38:53 -040027import android.os.Parcel;
28import android.os.Parcelable;
Jason Monkd9edfa942017-09-25 12:38:53 -040029
Mady Mellor4575aa52017-09-29 09:49:59 -070030import com.android.internal.util.ArrayUtils;
Jason Monk89389322018-05-15 21:13:16 -040031import com.android.internal.util.Preconditions;
Mady Mellor4575aa52017-09-29 09:49:59 -070032
Jeff Sharkey5db9a912017-12-08 17:32:32 -070033import java.lang.annotation.Retention;
34import java.lang.annotation.RetentionPolicy;
Jason Monkd9edfa942017-09-25 12:38:53 -040035import java.util.ArrayList;
36import java.util.Arrays;
Jason Monkd18651f2017-10-05 14:18:49 -040037import java.util.List;
Jason Monkd054fb32017-11-07 21:52:10 -050038import java.util.Objects;
Jason Monkd9edfa942017-09-25 12:38:53 -040039
40/**
41 * A slice is a piece of app content and actions that can be surfaced outside of the app.
42 *
43 * <p>They are constructed using {@link Builder} in a tree structure
44 * that provides the OS some information about how the content should be displayed.
Jason Monkd9edfa942017-09-25 12:38:53 -040045 */
46public final class Slice implements Parcelable {
47
48 /**
49 * @hide
50 */
Jeff Sharkey5db9a912017-12-08 17:32:32 -070051 @StringDef(prefix = { "HINT_" }, value = {
52 HINT_TITLE,
53 HINT_LIST,
54 HINT_LIST_ITEM,
55 HINT_LARGE,
56 HINT_ACTIONS,
57 HINT_SELECTED,
58 HINT_NO_TINT,
Mady Mellor225e0da2017-11-02 14:09:12 -070059 HINT_SHORTCUT,
Jeff Sharkey5db9a912017-12-08 17:32:32 -070060 HINT_TOGGLE,
61 HINT_HORIZONTAL,
62 HINT_PARTIAL,
Mady Mellor15e2c5d2018-03-01 16:46:56 -080063 HINT_SEE_MORE,
Mady Mellor930f9a52018-03-16 09:30:28 -070064 HINT_KEYWORDS,
Jason Monk106387f2018-03-06 16:32:28 -050065 HINT_ERROR,
Mady Mellor930f9a52018-03-16 09:30:28 -070066 HINT_TTL,
67 HINT_LAST_UPDATED,
Mady Mellor33c5a842018-03-19 16:23:15 -070068 HINT_PERMISSION_REQUEST,
Jeff Sharkey5db9a912017-12-08 17:32:32 -070069 })
70 @Retention(RetentionPolicy.SOURCE)
71 public @interface SliceHint {}
Jason Monk106387f2018-03-06 16:32:28 -050072 /**
73 * @hide
74 */
75 @StringDef(prefix = { "SUBTYPE_" }, value = {
76 SUBTYPE_COLOR,
77 SUBTYPE_CONTENT_DESCRIPTION,
78 SUBTYPE_MAX,
79 SUBTYPE_MESSAGE,
80 SUBTYPE_PRIORITY,
81 SUBTYPE_RANGE,
82 SUBTYPE_SOURCE,
83 SUBTYPE_TOGGLE,
84 SUBTYPE_VALUE,
Mady Mellor209af082018-03-30 14:06:26 -070085 SUBTYPE_LAYOUT_DIRECTION,
Jason Monk106387f2018-03-06 16:32:28 -050086 })
87 @Retention(RetentionPolicy.SOURCE)
88 public @interface SliceSubtype {}
Jason Monkd9edfa942017-09-25 12:38:53 -040089
90 /**
Mady Mellorb367fb72017-10-24 11:44:16 -070091 * Hint that this content is a title of other content in the slice. This can also indicate that
92 * the content should be used in the shortcut representation of the slice (icon, label, action),
93 * normally this should be indicated by adding the hint on the action containing that content.
94 *
Jason Monkd054fb32017-11-07 21:52:10 -050095 * @see SliceItem#FORMAT_ACTION
Jason Monkd9edfa942017-09-25 12:38:53 -040096 */
97 public static final String HINT_TITLE = "title";
98 /**
99 * Hint that all sub-items/sub-slices within this content should be considered
100 * to have {@link #HINT_LIST_ITEM}.
101 */
102 public static final String HINT_LIST = "list";
103 /**
104 * Hint that this item is part of a list and should be formatted as if is part
105 * of a list.
106 */
107 public static final String HINT_LIST_ITEM = "list_item";
108 /**
109 * Hint that this content is important and should be larger when displayed if
110 * possible.
111 */
112 public static final String HINT_LARGE = "large";
113 /**
114 * Hint that this slice contains a number of actions that can be grouped together
115 * in a sort of controls area of the UI.
116 */
117 public static final String HINT_ACTIONS = "actions";
118 /**
119 * Hint indicating that this item (and its sub-items) are the current selection.
120 */
121 public static final String HINT_SELECTED = "selected";
122 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400123 * Hint to indicate that this content should not be tinted.
124 */
125 public static final String HINT_NO_TINT = "no_tint";
Jason Monkd18651f2017-10-05 14:18:49 -0400126 /**
Mady Mellor225e0da2017-11-02 14:09:12 -0700127 * Hint to indicate that this content should only be displayed if the slice is presented
128 * as a shortcut.
Mady Mellorb367fb72017-10-24 11:44:16 -0700129 */
Mady Mellor225e0da2017-11-02 14:09:12 -0700130 public static final String HINT_SHORTCUT = "shortcut";
Mady Mellorb367fb72017-10-24 11:44:16 -0700131 /**
Mady Mellor39bf4352017-12-11 16:52:18 -0800132 * Hint indicating this content should be shown instead of the normal content when the slice
133 * is in small format.
134 */
135 public static final String HINT_SUMMARY = "summary";
136 /**
Mady Mellorfc2b3402017-11-08 14:15:43 -0800137 * Hint to indicate that this content has a toggle action associated with it. To indicate that
138 * the toggle is on, use {@link #HINT_SELECTED}. When the toggle state changes, the intent
139 * associated with it will be sent along with an extra {@link #EXTRA_TOGGLE_STATE} which can be
140 * retrieved to see the new state of the toggle.
141 * @hide
142 */
143 public static final String HINT_TOGGLE = "toggle";
144 /**
Jason Monkd054fb32017-11-07 21:52:10 -0500145 * Hint that list items within this slice or subslice would appear better
146 * if organized horizontally.
147 */
148 public static final String HINT_HORIZONTAL = "horizontal";
149 /**
Jason Monkd18651f2017-10-05 14:18:49 -0400150 * Hint to indicate that this slice is incomplete and an update will be sent once
151 * loading is complete. Slices which contain HINT_PARTIAL will not be cached by the
152 * OS and should not be cached by apps.
153 */
154 public static final String HINT_PARTIAL = "partial";
Jason Monk740a6502017-12-10 13:49:59 -0500155 /**
Mady Mellorfd1cbb82018-01-10 14:27:03 -0800156 * A hint representing that this item should be used to indicate that there's more
157 * content associated with this slice.
158 */
159 public static final String HINT_SEE_MORE = "see_more";
Mady Mellorfc2b3402017-11-08 14:15:43 -0800160 /**
Jason Monkb8e5fa92018-03-06 17:50:20 -0500161 * @see Builder#setCallerNeeded
162 * @hide
Jason Monke8f8be72018-01-21 10:10:35 -0500163 */
164 public static final String HINT_CALLER_NEEDED = "caller_needed";
165 /**
Mady Mellor15e2c5d2018-03-01 16:46:56 -0800166 * A hint to indicate that the contents of this subslice represent a list of keywords
167 * related to the parent slice.
Jason Monk106387f2018-03-06 16:32:28 -0500168 * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE}.
Mady Mellor15e2c5d2018-03-01 16:46:56 -0800169 */
Mady Mellor930f9a52018-03-16 09:30:28 -0700170 public static final String HINT_KEYWORDS = "keywords";
Mady Mellor15e2c5d2018-03-01 16:46:56 -0800171 /**
Jason Monk106387f2018-03-06 16:32:28 -0500172 * A hint to indicate that this slice represents an error.
173 */
174 public static final String HINT_ERROR = "error";
175 /**
Mady Mellor930f9a52018-03-16 09:30:28 -0700176 * Hint indicating an item representing a time-to-live for the content.
177 */
178 public static final String HINT_TTL = "ttl";
179 /**
180 * Hint indicating an item representing when the content was created or last updated.
181 */
182 public static final String HINT_LAST_UPDATED = "last_updated";
183 /**
Mady Mellor33c5a842018-03-19 16:23:15 -0700184 * A hint to indicate that this slice represents a permission request for showing
185 * slices.
186 */
187 public static final String HINT_PERMISSION_REQUEST = "permission_request";
188 /**
Mady Mellor209af082018-03-30 14:06:26 -0700189 * Subtype to indicate that this item indicates the layout direction for content
190 * in the slice.
191 * Expected to be an item of format {@link SliceItem#FORMAT_INT}.
192 */
193 public static final String SUBTYPE_LAYOUT_DIRECTION = "layout_direction";
194 /**
Mady Mellorfc2b3402017-11-08 14:15:43 -0800195 * Key to retrieve an extra added to an intent when a control is changed.
Mady Mellorfc2b3402017-11-08 14:15:43 -0800196 */
197 public static final String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
Jason Monkd054fb32017-11-07 21:52:10 -0500198 /**
Amin Shaikha1511702018-01-17 14:30:47 -0500199 * Key to retrieve an extra added to an intent when the value of a slider is changed.
Amin Shaikh60593c22018-01-30 10:35:59 -0500200 * @deprecated remove once support lib is update to use EXTRA_RANGE_VALUE instead
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600201 * @removed
Amin Shaikha1511702018-01-17 14:30:47 -0500202 */
Amin Shaikh60593c22018-01-30 10:35:59 -0500203 @Deprecated
Amin Shaikha1511702018-01-17 14:30:47 -0500204 public static final String EXTRA_SLIDER_VALUE = "android.app.slice.extra.SLIDER_VALUE";
205 /**
Amin Shaikh60593c22018-01-30 10:35:59 -0500206 * Key to retrieve an extra added to an intent when the value of an input range is changed.
207 */
208 public static final String EXTRA_RANGE_VALUE = "android.app.slice.extra.RANGE_VALUE";
209 /**
Jason Monkd054fb32017-11-07 21:52:10 -0500210 * Subtype to indicate that this is a message as part of a communication
211 * sequence in this slice.
Jason Monk106387f2018-03-06 16:32:28 -0500212 * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE}.
Jason Monkd054fb32017-11-07 21:52:10 -0500213 */
214 public static final String SUBTYPE_MESSAGE = "message";
215 /**
216 * Subtype to tag the source (i.e. sender) of a {@link #SUBTYPE_MESSAGE}.
Jason Monk106387f2018-03-06 16:32:28 -0500217 * Expected to be on an item of format {@link SliceItem#FORMAT_TEXT},
218 * {@link SliceItem#FORMAT_IMAGE} or an {@link SliceItem#FORMAT_SLICE} containing them.
Jason Monkd054fb32017-11-07 21:52:10 -0500219 */
220 public static final String SUBTYPE_SOURCE = "source";
Jason Monk740a6502017-12-10 13:49:59 -0500221 /**
222 * Subtype to tag an item as representing a color.
Jason Monk106387f2018-03-06 16:32:28 -0500223 * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
Jason Monk740a6502017-12-10 13:49:59 -0500224 */
225 public static final String SUBTYPE_COLOR = "color";
226 /**
Amin Shaikha1511702018-01-17 14:30:47 -0500227 * Subtype to tag an item as representing a slider.
Amin Shaikh60593c22018-01-30 10:35:59 -0500228 * @deprecated remove once support lib is update to use SUBTYPE_RANGE instead
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600229 * @removed
Jason Monk740a6502017-12-10 13:49:59 -0500230 */
Amin Shaikh60593c22018-01-30 10:35:59 -0500231 @Deprecated
Jason Monk740a6502017-12-10 13:49:59 -0500232 public static final String SUBTYPE_SLIDER = "slider";
Mady Mellor79e7ce32017-11-27 18:25:32 -0800233 /**
Amin Shaikh60593c22018-01-30 10:35:59 -0500234 * Subtype to tag an item as representing a range.
Jason Monk106387f2018-03-06 16:32:28 -0500235 * Expected to be on an item of format {@link SliceItem#FORMAT_SLICE} containing
236 * a {@link #SUBTYPE_VALUE} and possibly a {@link #SUBTYPE_MAX}.
Amin Shaikh60593c22018-01-30 10:35:59 -0500237 */
238 public static final String SUBTYPE_RANGE = "range";
239 /**
240 * Subtype to tag an item as representing the max int value for a {@link #SUBTYPE_RANGE}.
Jason Monk106387f2018-03-06 16:32:28 -0500241 * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
Amin Shaikha1511702018-01-17 14:30:47 -0500242 */
243 public static final String SUBTYPE_MAX = "max";
244 /**
Amin Shaikh60593c22018-01-30 10:35:59 -0500245 * Subtype to tag an item as representing the current int value for a {@link #SUBTYPE_RANGE}.
Jason Monk106387f2018-03-06 16:32:28 -0500246 * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
Amin Shaikha1511702018-01-17 14:30:47 -0500247 */
248 public static final String SUBTYPE_VALUE = "value";
249 /**
Mady Mellor79e7ce32017-11-27 18:25:32 -0800250 * Subtype to indicate that this content has a toggle action associated with it. To indicate
251 * that the toggle is on, use {@link #HINT_SELECTED}. When the toggle state changes, the
252 * intent associated with it will be sent along with an extra {@link #EXTRA_TOGGLE_STATE}
253 * which can be retrieved to see the new state of the toggle.
254 */
255 public static final String SUBTYPE_TOGGLE = "toggle";
Mady Mellorca8e8842017-12-20 09:57:53 -0800256 /**
257 * Subtype to tag an item representing priority.
Jason Monk106387f2018-03-06 16:32:28 -0500258 * Expected to be on an item of format {@link SliceItem#FORMAT_INT}.
Mady Mellorca8e8842017-12-20 09:57:53 -0800259 */
260 public static final String SUBTYPE_PRIORITY = "priority";
Mady Mellor0c99ecc2017-12-20 10:01:40 -0800261 /**
262 * Subtype to tag an item to use as a content description.
Jason Monk106387f2018-03-06 16:32:28 -0500263 * Expected to be on an item of format {@link SliceItem#FORMAT_TEXT}.
Mady Mellor0c99ecc2017-12-20 10:01:40 -0800264 */
265 public static final String SUBTYPE_CONTENT_DESCRIPTION = "content_description";
Mady Mellor930f9a52018-03-16 09:30:28 -0700266 /**
267 * Subtype to tag an item as representing a time in milliseconds since midnight,
268 * January 1, 1970 UTC.
269 */
270 public static final String SUBTYPE_MILLIS = "millis";
Jason Monkd9edfa942017-09-25 12:38:53 -0400271
272 private final SliceItem[] mItems;
273 private final @SliceHint String[] mHints;
Jason Monk2af19982017-11-07 19:38:27 -0500274 private SliceSpec mSpec;
Jason Monkd9edfa942017-09-25 12:38:53 -0400275 private Uri mUri;
276
Jason Monk2af19982017-11-07 19:38:27 -0500277 Slice(ArrayList<SliceItem> items, @SliceHint String[] hints, Uri uri, SliceSpec spec) {
Jason Monkd9edfa942017-09-25 12:38:53 -0400278 mHints = hints;
279 mItems = items.toArray(new SliceItem[items.size()]);
280 mUri = uri;
Jason Monk2af19982017-11-07 19:38:27 -0500281 mSpec = spec;
Jason Monkd9edfa942017-09-25 12:38:53 -0400282 }
283
284 protected Slice(Parcel in) {
285 mHints = in.readStringArray();
286 int n = in.readInt();
287 mItems = new SliceItem[n];
288 for (int i = 0; i < n; i++) {
289 mItems[i] = SliceItem.CREATOR.createFromParcel(in);
290 }
291 mUri = Uri.CREATOR.createFromParcel(in);
Jason Monk2af19982017-11-07 19:38:27 -0500292 mSpec = in.readTypedObject(SliceSpec.CREATOR);
293 }
294
295 /**
296 * @return The spec for this slice
297 */
298 public @Nullable SliceSpec getSpec() {
299 return mSpec;
Jason Monkd9edfa942017-09-25 12:38:53 -0400300 }
301
302 /**
Mady Mellor4575aa52017-09-29 09:49:59 -0700303 * @return The Uri that this Slice represents.
Jason Monkd9edfa942017-09-25 12:38:53 -0400304 */
305 public Uri getUri() {
306 return mUri;
307 }
308
309 /**
310 * @return All child {@link SliceItem}s that this Slice contains.
311 */
Jason Monkd18651f2017-10-05 14:18:49 -0400312 public List<SliceItem> getItems() {
313 return Arrays.asList(mItems);
Jason Monkd9edfa942017-09-25 12:38:53 -0400314 }
315
316 /**
317 * @return All hints associated with this Slice.
318 */
Jason Monkd18651f2017-10-05 14:18:49 -0400319 public @SliceHint List<String> getHints() {
320 return Arrays.asList(mHints);
Jason Monkd9edfa942017-09-25 12:38:53 -0400321 }
322
Jason Monkd9edfa942017-09-25 12:38:53 -0400323 @Override
324 public void writeToParcel(Parcel dest, int flags) {
325 dest.writeStringArray(mHints);
326 dest.writeInt(mItems.length);
327 for (int i = 0; i < mItems.length; i++) {
328 mItems[i].writeToParcel(dest, flags);
329 }
330 mUri.writeToParcel(dest, 0);
Jason Monk2af19982017-11-07 19:38:27 -0500331 dest.writeTypedObject(mSpec, flags);
Jason Monkd9edfa942017-09-25 12:38:53 -0400332 }
333
334 @Override
335 public int describeContents() {
336 return 0;
337 }
338
339 /**
Mady Mellor4575aa52017-09-29 09:49:59 -0700340 * @hide
341 */
342 public boolean hasHint(@SliceHint String hint) {
343 return ArrayUtils.contains(mHints, hint);
344 }
345
346 /**
Jason Monkb8e5fa92018-03-06 17:50:20 -0500347 * Returns whether the caller for this slice matters.
348 * @see Builder#setCallerNeeded
349 */
350 public boolean isCallerNeeded() {
351 return hasHint(HINT_CALLER_NEEDED);
352 }
353
354 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400355 * A Builder used to construct {@link Slice}s
356 */
357 public static class Builder {
358
359 private final Uri mUri;
360 private ArrayList<SliceItem> mItems = new ArrayList<>();
361 private @SliceHint ArrayList<String> mHints = new ArrayList<>();
Jason Monk2af19982017-11-07 19:38:27 -0500362 private SliceSpec mSpec;
Jason Monkd9edfa942017-09-25 12:38:53 -0400363
364 /**
Jason Monk106387f2018-03-06 16:32:28 -0500365 * @deprecated TO BE REMOVED
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600366 * @removed
Jason Monkd9edfa942017-09-25 12:38:53 -0400367 */
Jason Monk106387f2018-03-06 16:32:28 -0500368 @Deprecated
Jason Monkd9edfa942017-09-25 12:38:53 -0400369 public Builder(@NonNull Uri uri) {
370 mUri = uri;
371 }
372
373 /**
Jason Monk106387f2018-03-06 16:32:28 -0500374 * Create a builder which will construct a {@link Slice} for the given Uri.
375 * @param uri Uri to tag for this slice.
376 * @param spec the spec for this slice.
377 */
378 public Builder(@NonNull Uri uri, SliceSpec spec) {
379 mUri = uri;
380 mSpec = spec;
381 }
382
383 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400384 * Create a builder for a {@link Slice} that is a sub-slice of the slice
385 * being constructed by the provided builder.
386 * @param parent The builder constructing the parent slice
387 */
388 public Builder(@NonNull Slice.Builder parent) {
389 mUri = parent.mUri.buildUpon().appendPath("_gen")
390 .appendPath(String.valueOf(mItems.size())).build();
391 }
392
393 /**
Jason Monkb8e5fa92018-03-06 17:50:20 -0500394 * Tells the system whether for this slice the return value of
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600395 * {@link SliceProvider#onBindSlice(Uri, java.util.Set)} may be different depending on
Jason Monkb8e5fa92018-03-06 17:50:20 -0500396 * {@link SliceProvider#getCallingPackage()} and should not be cached for multiple
397 * apps.
398 */
399 public Builder setCallerNeeded(boolean callerNeeded) {
400 if (callerNeeded) {
401 mHints.add(HINT_CALLER_NEEDED);
402 } else {
403 mHints.remove(HINT_CALLER_NEEDED);
404 }
405 return this;
406 }
407
408 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400409 * Add hints to the Slice being constructed
410 */
Jason Monk106387f2018-03-06 16:32:28 -0500411 public Builder addHints(@SliceHint List<String> hints) {
412 mHints.addAll(hints);
Jason Monkd9edfa942017-09-25 12:38:53 -0400413 return this;
414 }
415
416 /**
Jason Monk106387f2018-03-06 16:32:28 -0500417 * @deprecated TO BE REMOVED
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600418 * @removed
Jason Monk2af19982017-11-07 19:38:27 -0500419 */
420 public Builder setSpec(SliceSpec spec) {
421 mSpec = spec;
422 return this;
423 }
424
425 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400426 * Add a sub-slice to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500427 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700428 * @see SliceItem#getSubType()
Jason Monkd054fb32017-11-07 21:52:10 -0500429 */
Jason Monk106387f2018-03-06 16:32:28 -0500430 public Builder addSubSlice(@NonNull Slice slice, @Nullable @SliceSubtype String subType) {
Jason Monk89389322018-05-15 21:13:16 -0400431 Preconditions.checkNotNull(slice);
Jason Monkd054fb32017-11-07 21:52:10 -0500432 mItems.add(new SliceItem(slice, SliceItem.FORMAT_SLICE, subType,
433 slice.getHints().toArray(new String[slice.getHints().size()])));
Jason Monkd9edfa942017-09-25 12:38:53 -0400434 return this;
435 }
436
437 /**
438 * Add an action to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500439 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700440 * @see SliceItem#getSubType()
Jason Monkd054fb32017-11-07 21:52:10 -0500441 */
442 public Slice.Builder addAction(@NonNull PendingIntent action, @NonNull Slice s,
Jason Monk106387f2018-03-06 16:32:28 -0500443 @Nullable @SliceSubtype String subType) {
Jason Monk89389322018-05-15 21:13:16 -0400444 Preconditions.checkNotNull(action);
445 Preconditions.checkNotNull(s);
Jason Monk2af19982017-11-07 19:38:27 -0500446 List<String> hints = s.getHints();
447 s.mSpec = null;
Jason Monkd054fb32017-11-07 21:52:10 -0500448 mItems.add(new SliceItem(action, s, SliceItem.FORMAT_ACTION, subType, hints.toArray(
Jason Monk2af19982017-11-07 19:38:27 -0500449 new String[hints.size()])));
Jason Monkd9edfa942017-09-25 12:38:53 -0400450 return this;
451 }
452
453 /**
454 * Add text to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500455 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700456 * @see SliceItem#getSubType()
Jason Monkd9edfa942017-09-25 12:38:53 -0400457 */
Jason Monk106387f2018-03-06 16:32:28 -0500458 public Builder addText(CharSequence text, @Nullable @SliceSubtype String subType,
459 @SliceHint List<String> hints) {
Jason Monkd054fb32017-11-07 21:52:10 -0500460 mItems.add(new SliceItem(text, SliceItem.FORMAT_TEXT, subType, hints));
Jason Monkd9edfa942017-09-25 12:38:53 -0400461 return this;
462 }
463
464 /**
Jason Monkd054fb32017-11-07 21:52:10 -0500465 * Add an image to the slice being constructed
466 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700467 * @see SliceItem#getSubType()
Jason Monkd054fb32017-11-07 21:52:10 -0500468 */
Jason Monk106387f2018-03-06 16:32:28 -0500469 public Builder addIcon(Icon icon, @Nullable @SliceSubtype String subType,
470 @SliceHint List<String> hints) {
Jason Monk89389322018-05-15 21:13:16 -0400471 Preconditions.checkNotNull(icon);
Jason Monkd054fb32017-11-07 21:52:10 -0500472 mItems.add(new SliceItem(icon, SliceItem.FORMAT_IMAGE, subType, hints));
473 return this;
474 }
475
476 /**
Jason Monkd18651f2017-10-05 14:18:49 -0400477 * Add remote input to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500478 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700479 * @see SliceItem#getSubType()
Jason Monkd18651f2017-10-05 14:18:49 -0400480 */
Jason Monk106387f2018-03-06 16:32:28 -0500481 public Slice.Builder addRemoteInput(RemoteInput remoteInput,
482 @Nullable @SliceSubtype String subType,
Jason Monkd054fb32017-11-07 21:52:10 -0500483 @SliceHint List<String> hints) {
Jason Monk89389322018-05-15 21:13:16 -0400484 Preconditions.checkNotNull(remoteInput);
Jason Monkd054fb32017-11-07 21:52:10 -0500485 mItems.add(new SliceItem(remoteInput, SliceItem.FORMAT_REMOTE_INPUT,
486 subType, hints));
Jason Monkd9edfa942017-09-25 12:38:53 -0400487 return this;
488 }
489
490 /**
Amin Shaikh31062cb2018-02-16 15:13:25 -0500491 * Add an integer to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500492 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700493 * @see SliceItem#getSubType()
Jason Monk740a6502017-12-10 13:49:59 -0500494 */
Jason Monk106387f2018-03-06 16:32:28 -0500495 public Builder addInt(int value, @Nullable @SliceSubtype String subType,
496 @SliceHint List<String> hints) {
Jason Monk740a6502017-12-10 13:49:59 -0500497 mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints));
Jason Monkd9edfa942017-09-25 12:38:53 -0400498 return this;
499 }
500
501 /**
Jason Monk106387f2018-03-06 16:32:28 -0500502 * @deprecated TO BE REMOVED.
Jeff Sharkey3990ee12018-04-11 10:19:55 -0600503 * @removed
Jason Monkd18651f2017-10-05 14:18:49 -0400504 */
Jason Monk106387f2018-03-06 16:32:28 -0500505 @Deprecated
506 public Slice.Builder addTimestamp(long time, @Nullable @SliceSubtype String subType,
Jason Monkd054fb32017-11-07 21:52:10 -0500507 @SliceHint List<String> hints) {
Jason Monk106387f2018-03-06 16:32:28 -0500508 return addLong(time, subType, hints);
Jason Monkd18651f2017-10-05 14:18:49 -0400509 }
510
511 /**
Jason Monk106387f2018-03-06 16:32:28 -0500512 * Add a long to the slice being constructed
Jason Monkd054fb32017-11-07 21:52:10 -0500513 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700514 * @see SliceItem#getSubType()
Jason Monkd9edfa942017-09-25 12:38:53 -0400515 */
Jason Monk106387f2018-03-06 16:32:28 -0500516 public Slice.Builder addLong(long value, @Nullable @SliceSubtype String subType,
517 @SliceHint List<String> hints) {
518 mItems.add(new SliceItem(value, SliceItem.FORMAT_LONG, subType,
519 hints.toArray(new String[hints.size()])));
Jason Monkd9edfa942017-09-25 12:38:53 -0400520 return this;
521 }
522
523 /**
Jason Monkfed72bf2017-12-08 18:19:32 -0500524 * Add a bundle to the slice being constructed.
525 * <p>Expected to be used for support library extension, should not be used for general
526 * development
527 * @param subType Optional template-specific type information
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700528 * @see SliceItem#getSubType()
Jason Monkfed72bf2017-12-08 18:19:32 -0500529 */
Jason Monk106387f2018-03-06 16:32:28 -0500530 public Slice.Builder addBundle(Bundle bundle, @Nullable @SliceSubtype String subType,
531 @SliceHint List<String> hints) {
Jason Monk89389322018-05-15 21:13:16 -0400532 Preconditions.checkNotNull(bundle);
Jason Monkfed72bf2017-12-08 18:19:32 -0500533 mItems.add(new SliceItem(bundle, SliceItem.FORMAT_BUNDLE, subType,
534 hints));
535 return this;
536 }
537
538 /**
Jason Monkd9edfa942017-09-25 12:38:53 -0400539 * Construct the slice.
540 */
541 public Slice build() {
Jason Monk2af19982017-11-07 19:38:27 -0500542 return new Slice(mItems, mHints.toArray(new String[mHints.size()]), mUri, mSpec);
Jason Monkd9edfa942017-09-25 12:38:53 -0400543 }
544 }
545
546 public static final Creator<Slice> CREATOR = new Creator<Slice>() {
547 @Override
548 public Slice createFromParcel(Parcel in) {
549 return new Slice(in);
550 }
551
552 @Override
553 public Slice[] newArray(int size) {
554 return new Slice[size];
555 }
556 };
Mady Mellor4575aa52017-09-29 09:49:59 -0700557
558 /**
559 * @hide
560 * @return A string representation of this slice.
561 */
Jason Monkd18651f2017-10-05 14:18:49 -0400562 public String toString() {
563 return toString("");
Mady Mellor4575aa52017-09-29 09:49:59 -0700564 }
565
Jason Monkd18651f2017-10-05 14:18:49 -0400566 private String toString(String indent) {
Mady Mellor4575aa52017-09-29 09:49:59 -0700567 StringBuilder sb = new StringBuilder();
568 for (int i = 0; i < mItems.length; i++) {
569 sb.append(indent);
Jason Monkd054fb32017-11-07 21:52:10 -0500570 if (Objects.equals(mItems[i].getFormat(), SliceItem.FORMAT_SLICE)) {
Mady Mellor4575aa52017-09-29 09:49:59 -0700571 sb.append("slice:\n");
Jason Monkd18651f2017-10-05 14:18:49 -0400572 sb.append(mItems[i].getSlice().toString(indent + " "));
Jason Monkd054fb32017-11-07 21:52:10 -0500573 } else if (Objects.equals(mItems[i].getFormat(), SliceItem.FORMAT_TEXT)) {
Mady Mellor4575aa52017-09-29 09:49:59 -0700574 sb.append("text: ");
575 sb.append(mItems[i].getText());
576 sb.append("\n");
577 } else {
Jason Monkd054fb32017-11-07 21:52:10 -0500578 sb.append(mItems[i].getFormat());
Mady Mellor4575aa52017-09-29 09:49:59 -0700579 sb.append("\n");
580 }
581 }
582 return sb.toString();
583 }
Jason Monkd9edfa942017-09-25 12:38:53 -0400584}