SliceMetadataTest.java revision 38db00ef5d4b5a9d0d171f1bb15a5df567d448f6
1/*
2 * Copyright 2018 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 androidx.slice;
18
19import static android.app.slice.Slice.HINT_PARTIAL;
20import static android.app.slice.Slice.HINT_TITLE;
21
22import static androidx.slice.SliceMetadata.LOADED_ALL;
23import static androidx.slice.SliceMetadata.LOADED_NONE;
24import static androidx.slice.SliceMetadata.LOADED_PARTIAL;
25import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
26import static androidx.slice.core.SliceHints.HINT_KEYWORDS;
27
28import static junit.framework.Assert.assertEquals;
29import static junit.framework.Assert.assertTrue;
30
31import static org.junit.Assert.assertArrayEquals;
32import static org.junit.Assert.assertNull;
33
34import android.app.PendingIntent;
35import android.content.Context;
36import android.content.Intent;
37import android.graphics.Bitmap;
38import android.graphics.Canvas;
39import android.net.Uri;
40import android.support.test.InstrumentationRegistry;
41import android.support.test.filters.SmallTest;
42import android.support.test.runner.AndroidJUnit4;
43
44import androidx.core.graphics.drawable.IconCompat;
45import androidx.core.util.Pair;
46import androidx.slice.builders.GridRowBuilder;
47import androidx.slice.builders.ListBuilder;
48import androidx.slice.builders.SliceAction;
49import androidx.slice.core.SliceActionImpl;
50import androidx.slice.core.SliceHints;
51import androidx.slice.render.SliceRenderActivity;
52import androidx.slice.widget.EventInfo;
53import androidx.slice.widget.SliceLiveData;
54
55import org.junit.Before;
56import org.junit.Test;
57import org.junit.runner.RunWith;
58
59import java.util.ArrayList;
60import java.util.List;
61import java.util.concurrent.TimeUnit;
62
63/**
64 * Tests for {@link SliceMetadata}.
65 */
66@RunWith(AndroidJUnit4.class)
67@SmallTest
68public class SliceMetadataTest {
69
70    private final Context mContext = InstrumentationRegistry.getContext();
71
72    @Before
73    public void setup() {
74        SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
75    }
76
77    @Test
78    public void testGetSliceActionsNull() {
79        Uri uri = Uri.parse("content://pkg/slice");
80
81        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
82        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("Text"));
83
84        SliceMetadata sliceMetadata = SliceMetadata.from(mContext, lb.build());
85        assertNull(sliceMetadata.getSliceActions());
86    }
87
88    @Test
89    public void testGetSliceActions() {
90        Uri uri = Uri.parse("content://pkg/slice");
91        PendingIntent pi = getIntent("");
92        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
93        new Canvas(b).drawColor(0xffff0000);
94        IconCompat icon = IconCompat.createWithBitmap(b);
95
96        SliceAction action1 = new SliceAction(pi, icon, "action1");
97        SliceAction action2 = new SliceAction(pi, icon, "action2");
98        SliceAction action3 = new SliceAction(pi, icon, "action3");
99
100        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
101        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("Text"))
102                .addAction(action1)
103                .addAction(action2)
104                .addAction(action3);
105
106        ArrayList<SliceAction> expectedActions = new ArrayList<>();
107        expectedActions.add(action1);
108        expectedActions.add(action2);
109        expectedActions.add(action3);
110
111        SliceMetadata sliceMetadata = SliceMetadata.from(mContext, lb.build());
112        List<SliceItem> actions = sliceMetadata.getSliceActions();
113
114        for (int i = 0; i < expectedActions.size(); i++) {
115            assertEquivalent(expectedActions.get(i), new SliceActionImpl(actions.get(i)));
116        }
117    }
118
119    @Test
120    public void testGetPrimaryActionForGrid() {
121        Uri uri = Uri.parse("content://pkg/slice");
122        PendingIntent pi = getIntent("");
123        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
124        new Canvas(b).drawColor(0xffff0000);
125        IconCompat icon = IconCompat.createWithBitmap(b);
126
127        SliceAction primaryAction = new SliceAction(pi, icon, "action");
128
129        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
130        GridRowBuilder grb = new GridRowBuilder(lb);
131        grb.setPrimaryAction(primaryAction);
132        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
133        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
134        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
135        lb.addGridRow(grb);
136
137        Slice gridSlice = lb.build();
138        SliceMetadata gridInfo = SliceMetadata.from(mContext, gridSlice);
139        assertEquivalent(primaryAction, gridInfo.getPrimaryAction());
140    }
141
142    @Test
143    public void testGetPrimaryActionForRow() {
144        Uri uri = Uri.parse("content://pkg/slice");
145        PendingIntent pi = getIntent("");
146        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
147        new Canvas(b).drawColor(0xffff0000);
148        IconCompat icon = IconCompat.createWithBitmap(b);
149
150        SliceAction primaryAction = new SliceAction(pi, icon, "action");
151        SliceAction endAction = new SliceAction(pi, "toogle action", false);
152
153        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
154        ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb)
155                .setTitle("a title")
156                .addEndItem(endAction)
157                .setPrimaryAction(primaryAction);
158        lb.addRow(rb);
159
160        Slice rowSlice = lb.build();
161        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
162        assertEquivalent(primaryAction, rowInfo.getPrimaryAction());
163    }
164
165    @Test
166    public void testGetPrimaryActionForHeader() {
167        Uri uri = Uri.parse("content://pkg/slice");
168        PendingIntent pi = getIntent("");
169        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
170        new Canvas(b).drawColor(0xffff0000);
171        IconCompat icon = IconCompat.createWithBitmap(b);
172
173        SliceAction primaryAction = new SliceAction(pi, icon, "action");
174        SliceAction sliceAction = new SliceAction(pi, "another action", true);
175
176        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
177        lb.addAction(sliceAction);
178        ListBuilder.HeaderBuilder hb = new ListBuilder.HeaderBuilder(lb);
179        hb.setTitle("header title");
180        hb.setPrimaryAction(primaryAction);
181        lb.setHeader(hb);
182
183        Slice headerSlice = lb.build();
184        SliceMetadata headerInfo = SliceMetadata.from(mContext, headerSlice);
185        assertEquivalent(primaryAction, headerInfo.getPrimaryAction());
186    }
187
188    @Test
189    public void testGetPrimaryActionNull() {
190        Uri uri = Uri.parse("content://pkg/slice");
191        PendingIntent pi = getIntent("");
192        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
193        new Canvas(b).drawColor(0xffff0000);
194        IconCompat icon = IconCompat.createWithBitmap(b);
195
196        SliceAction endAction1 = new SliceAction(pi, icon, "action");
197        SliceAction endAction2 = new SliceAction(pi, "toogle action", false);
198
199        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
200        ListBuilder.RowBuilder rb = new ListBuilder.RowBuilder(lb)
201                .setTitle("a title")
202                .addEndItem(endAction1)
203                .addEndItem(endAction2);
204        lb.addRow(rb);
205
206        Slice rowSlice = lb.build();
207        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
208        assertNull(rowInfo.getPrimaryAction());
209    }
210
211    @Test
212    public void testGetHeaderTypeGrid() {
213        Uri uri = Uri.parse("content://pkg/slice");
214
215        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
216        GridRowBuilder grb = new GridRowBuilder(lb);
217        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
218        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
219        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
220        lb.addGridRow(grb);
221
222        Slice gridSlice = lb.build();
223        SliceMetadata gridInfo = SliceMetadata.from(mContext, gridSlice);
224        assertEquals(EventInfo.ROW_TYPE_GRID, gridInfo.getHeaderType());
225    }
226
227    @Test
228    public void testGetHeaderTypeRow() {
229        Uri uri = Uri.parse("content://pkg/slice");
230
231        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
232        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("a title"));
233
234        Slice rowSlice = lb.build();
235        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
236        assertEquals(EventInfo.ROW_TYPE_LIST, rowInfo.getHeaderType());
237    }
238
239    @Test
240    public void testGetHeaderTypeToggle() {
241        Uri uri = Uri.parse("content://pkg/slice");
242        PendingIntent pi = getIntent("");
243
244        SliceAction toggleAction = new SliceAction(pi, "toggle", false /* isChecked */);
245        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
246        lb.addRow(new ListBuilder.RowBuilder(lb)
247                .setTitle("another title")
248                .addEndItem(toggleAction));
249
250        Slice toggleSlice = lb.build();
251        SliceMetadata toggleInfo = SliceMetadata.from(mContext, toggleSlice);
252        assertEquals(EventInfo.ROW_TYPE_TOGGLE, toggleInfo.getHeaderType());
253    }
254
255    @Test
256    public void testGetHeaderTypeSlider() {
257        Uri uri = Uri.parse("content://pkg/slice");
258        PendingIntent pi = getIntent("");
259
260        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
261        lb.addInputRange(new ListBuilder.InputRangeBuilder(lb)
262                .setTitle("another title")
263                .setValue(5)
264                .setMax(10)
265                .setAction(pi));
266
267        Slice sliderSlice = lb.build();
268        SliceMetadata sliderInfo = SliceMetadata.from(mContext, sliderSlice);
269        assertEquals(EventInfo.ROW_TYPE_SLIDER, sliderInfo.getHeaderType());
270    }
271
272    @Test
273    public void testGetHeaderTypeProgress() {
274        Uri uri = Uri.parse("content://pkg/slice");
275
276        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
277        lb.addRange(new ListBuilder.RangeBuilder(lb)
278                .setTitle("another title")
279                .setValue(5)
280                .setMax(10));
281
282        Slice sliderSlice = lb.build();
283        SliceMetadata progressInfo = SliceMetadata.from(mContext, sliderSlice);
284        assertEquals(EventInfo.ROW_TYPE_PROGRESS, progressInfo.getHeaderType());
285    }
286
287    @Test
288    public void testGetHeaderTypeHeader() {
289        Uri uri = Uri.parse("content://pkg/slice");
290
291        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
292        ListBuilder.HeaderBuilder hb = new ListBuilder.HeaderBuilder(lb);
293        hb.setTitle("header title");
294        lb.setHeader(hb);
295
296        Slice headerSlice = lb.build();
297        SliceMetadata headerInfo = SliceMetadata.from(mContext, headerSlice);
298        assertEquals(EventInfo.ROW_TYPE_LIST, headerInfo.getHeaderType());
299    }
300
301    @Test
302    public void testHasLargeModeFullGrid() {
303        // If a grid is "full" with two text and an image there is a different small / large state.
304        Uri uri = Uri.parse("content://pkg/slice");
305        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
306        new Canvas(b).drawColor(0xffff0000);
307        IconCompat icon = IconCompat.createWithBitmap(b);
308
309        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
310        GridRowBuilder grb = new GridRowBuilder(lb);
311        grb.addCell(new GridRowBuilder.CellBuilder(grb)
312                .addText("some text")
313                .addText("more text")
314                .addImage(icon, ICON_IMAGE));
315        grb.addCell(new GridRowBuilder.CellBuilder(grb)
316                .addText("some text")
317                .addText("more text")
318                .addImage(icon, ICON_IMAGE));
319        grb.addCell(new GridRowBuilder.CellBuilder(grb)
320                .addText("some text")
321                .addText("more text")
322                .addImage(icon, ICON_IMAGE));
323        lb.addGridRow(grb);
324
325        Slice gridSlice = lb.build();
326        SliceMetadata gridInfo = SliceMetadata.from(mContext, gridSlice);
327        assertTrue(gridInfo.hasLargeMode());
328    }
329
330    @Test
331    public void testHasLargeModeGrid() {
332        // If a grid is not "full" either no image or an image and one text item, small / large
333        // is the same.
334        Uri uri = Uri.parse("content://pkg/slice");
335
336        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
337        GridRowBuilder grb = new GridRowBuilder(lb);
338        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
339        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
340        grb.addCell(new GridRowBuilder.CellBuilder(grb).addText("some text"));
341        lb.addGridRow(grb);
342
343        Slice gridSlice = lb.build();
344        SliceMetadata gridInfo = SliceMetadata.from(mContext, gridSlice);
345        assertTrue(!gridInfo.hasLargeMode());
346    }
347
348    @Test
349    public void testGetLargeModeMultipleRows() {
350        Uri uri = Uri.parse("content://pkg/slice");
351
352        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
353        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("a title"));
354        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("another row another title"));
355
356        Slice rowSlice = lb.build();
357        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
358        assertTrue(rowInfo.hasLargeMode());
359    }
360
361    @Test
362    public void testGetLargeModeSingleRow() {
363        Uri uri = Uri.parse("content://pkg/slice");
364
365        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
366        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("a title"));
367
368        Slice rowSlice = lb.build();
369        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
370        assertTrue(!rowInfo.hasLargeMode());
371    }
372
373    @Test
374    public void testGetTogglesNone() {
375        Uri uri = Uri.parse("content://pkg/slice");
376
377        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
378        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("a title"));
379
380        Slice rowSlice = lb.build();
381        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
382        assertTrue(rowInfo.getToggles().isEmpty());
383    }
384
385    @Test
386    public void testGetTogglesSingle() {
387        Uri uri = Uri.parse("content://pkg/slice");
388        PendingIntent pi = getIntent("");
389
390        SliceAction toggleAction = new SliceAction(pi, "toggle", false /* isChecked */);
391        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
392        lb.addRow(new ListBuilder.RowBuilder(lb)
393                .setTitle("another title")
394                .addEndItem(toggleAction));
395
396        Slice toggleSlice = lb.build();
397        SliceMetadata toggleInfo = SliceMetadata.from(mContext, toggleSlice);
398        List<androidx.slice.core.SliceAction> actualToggles = toggleInfo.getToggles();
399        assertEquals(1, actualToggles.size());
400        assertEquivalent(toggleAction, actualToggles.get(0));
401    }
402
403    @Test
404    public void testGetTogglesMultiple() {
405        Uri uri = Uri.parse("content://pkg/slice");
406        PendingIntent pi = getIntent("");
407        Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
408        new Canvas(b).drawColor(0xffff0000);
409        IconCompat icon = IconCompat.createWithBitmap(b);
410
411        SliceAction toggleAction = new SliceAction(pi, icon, "toggle", false /* isChecked */);
412        SliceAction toggleAction2 = new SliceAction(pi, icon, "toggle2", true /* isChecked */);
413
414        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
415        lb.addRow(new ListBuilder.RowBuilder(lb)
416                .setTitle("another title")
417                .addEndItem(toggleAction)
418                .addEndItem(toggleAction2));
419
420        Slice toggleSlice = lb.build();
421        SliceMetadata toggleInfo = SliceMetadata.from(mContext, toggleSlice);
422        List<androidx.slice.core.SliceAction> actualToggles = toggleInfo.getToggles();
423
424        List<SliceAction> expectedToggles = new ArrayList<>();
425        expectedToggles.add(toggleAction);
426        expectedToggles.add(toggleAction2);
427
428        for (int i = 0; i < expectedToggles.size(); i++) {
429            assertEquivalent(expectedToggles.get(i), actualToggles.get(i));
430        }
431    }
432
433    @Test
434    public void testGetRangeNull() {
435        Uri uri = Uri.parse("content://pkg/slice");
436
437        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
438        lb.addRow(new ListBuilder.RowBuilder(lb).setTitle("a title"));
439
440        Slice rowSlice = lb.build();
441        SliceMetadata rowInfo = SliceMetadata.from(mContext, rowSlice);
442        assertNull(rowInfo.getRange());
443    }
444
445    @Test
446    public void testGetRangeForSlider() {
447        Uri uri = Uri.parse("content://pkg/slice");
448        PendingIntent pi = getIntent("");
449
450        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
451        lb.addInputRange(new ListBuilder.InputRangeBuilder(lb)
452                .setTitle("another title")
453                .setValue(7)
454                .setMin(5)
455                .setMax(10)
456                .setInputAction(pi));
457
458        Slice sliderSlice = lb.build();
459        SliceMetadata sliderInfo = SliceMetadata.from(mContext, sliderSlice);
460
461        Pair<Integer, Integer> values = sliderInfo.getRange();
462        assertEquals(5, (int) values.first);
463        assertEquals(10, (int) values.second);
464
465        int currentValue = sliderInfo.getRangeValue();
466        assertEquals(7, currentValue);
467    }
468
469    @Test
470    public void testGetRangeForProgress() {
471        Uri uri = Uri.parse("content://pkg/slice");
472
473        ListBuilder lb = new ListBuilder(mContext, uri, ListBuilder.INFINITY);
474        lb.addRange(new ListBuilder.RangeBuilder(lb)
475                .setTitle("another title")
476                .setValue(5)
477                .setMax(10));
478
479        Slice sliderSlice = lb.build();
480        SliceMetadata progressInfo = SliceMetadata.from(mContext, sliderSlice);
481        Pair<Integer, Integer> values = progressInfo.getRange();
482        assertEquals(0, (int) values.first);
483        assertEquals(10, (int) values.second);
484    }
485
486    @Test
487    public void testKeywords() {
488        Uri uri = Uri.parse("content://pkg/slice");
489        Slice keywordSlice = new Slice.Builder(uri)
490                .addHints(HINT_KEYWORDS)
491                .addText("keyword1", null)
492                .addText("keyword2", null)
493                .addText("keyword3", null).build();
494        Slice slice = new Slice.Builder(uri)
495                .addText("Some text", null, HINT_TITLE)
496                .addText("Some other text", null)
497                .addSubSlice(keywordSlice)
498                .build();
499
500        SliceMetadata SliceMetadata1 = SliceMetadata.from(mContext, slice);
501        List<String> sliceKeywords = SliceMetadata1.getSliceKeywords();
502        String[] expectedList = new String[] {"keyword1", "keyword2", "keyword3"};
503        assertArrayEquals(expectedList, sliceKeywords.toArray());
504
505        // Make sure it doesn't find keywords that aren't there
506        Slice slice2 = new Slice.Builder(uri)
507                .addText("Some text", null, HINT_TITLE)
508                .addText("Some other text", null).build();
509
510        SliceMetadata SliceMetadata2 = SliceMetadata.from(mContext, slice2);
511        List<String> slice2Keywords = SliceMetadata2.getSliceKeywords();
512        assertNull(slice2Keywords);
513
514        // Make sure empty list if specified to have no keywords
515        Slice noKeywordSlice = new Slice.Builder(uri).addHints(HINT_KEYWORDS).build();
516        Slice slice3 = new Slice.Builder(uri)
517                .addText("Some text", null, HINT_TITLE)
518                .addSubSlice(noKeywordSlice)
519                .build();
520
521        SliceMetadata sliceMetadata3 = SliceMetadata.from(mContext, slice3);
522        List<String> slice3Keywords = sliceMetadata3.getSliceKeywords();
523        assertTrue(slice3Keywords.isEmpty());
524    }
525
526    @Test
527    public void testGetLoadingState() {
528        Uri uri = Uri.parse("content://pkg/slice");
529        Slice s1 = new Slice.Builder(uri).build();
530        SliceMetadata SliceMetadata1 = SliceMetadata.from(mContext, s1);
531        int actualState1 = SliceMetadata1.getLoadingState();
532        assertEquals(LOADED_NONE, actualState1);
533
534        Slice s2 = new Slice.Builder(uri).addText(null, null, HINT_PARTIAL).build();
535        SliceMetadata SliceMetadata2 = SliceMetadata.from(mContext, s2);
536        int actualState2 = SliceMetadata2.getLoadingState();
537        assertEquals(LOADED_PARTIAL, actualState2);
538
539        Slice s3 = new Slice.Builder(uri).addText("Text", null).build();
540        SliceMetadata SliceMetadata3 = SliceMetadata.from(mContext, s3);
541        int actualState3 = SliceMetadata3.getLoadingState();
542        assertEquals(LOADED_ALL, actualState3);
543    }
544
545    @Test
546    public void testGetExpiry() {
547        Uri uri = Uri.parse("content://pkg/slice");
548        long timestamp = System.currentTimeMillis();
549        long ttl = TimeUnit.DAYS.toMillis(1);
550        Slice ttlSlice = new Slice.Builder(uri)
551                .addText("Some text", null)
552                .addTimestamp(timestamp, null)
553                .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
554                .addTimestamp(ttl, null, SliceHints.HINT_TTL)
555                .build();
556
557        SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
558        long retrievedTtl = si1.getExpiry();
559        assertEquals(ttl, retrievedTtl);
560
561        Slice noTtlSlice = new Slice.Builder(uri)
562                .addText("Some text", null)
563                .addTimestamp(timestamp, null).build();
564        SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
565        long retrievedTtl2 = si2.getExpiry();
566        assertEquals(0, retrievedTtl2);
567    }
568
569    @Test
570    public void testGetLastUpdated() {
571        Uri uri = Uri.parse("content://pkg/slice");
572        long timestamp = System.currentTimeMillis();
573        long ttl = TimeUnit.DAYS.toMillis(1);
574        Slice ttlSlice = new Slice.Builder(uri)
575                .addText("Some text", null)
576                .addTimestamp(timestamp - 20, null)
577                .addTimestamp(timestamp, null, SliceHints.HINT_LAST_UPDATED)
578                .addTimestamp(ttl, null, SliceHints.HINT_TTL)
579                .build();
580
581        SliceMetadata si1 = SliceMetadata.from(mContext, ttlSlice);
582        long retrievedLastUpdated = si1.getLastUpdatedTime();
583        assertEquals(timestamp, retrievedLastUpdated);
584
585        Slice noTtlSlice = new Slice.Builder(uri)
586                .addText("Some text", null)
587                .addTimestamp(timestamp, null).build();
588
589        SliceMetadata si2 = SliceMetadata.from(mContext, noTtlSlice);
590        long retrievedLastUpdated2 = si2.getLastUpdatedTime();
591        assertEquals(0, retrievedLastUpdated2);
592    }
593
594    @Test
595    public void testIsPermissionSlice() {
596        Uri uri = Uri.parse("content://pkg/slice");
597        Slice permissionSlice =
598                SliceProvider.createPermissionSlice(mContext, uri, mContext.getPackageName());
599
600        SliceMetadata metadata = SliceMetadata.from(mContext, permissionSlice);
601        assertEquals(true, metadata.isPermissionSlice());
602    }
603
604    private PendingIntent getIntent(String action) {
605        Intent intent = new Intent(action);
606        intent.setClassName(mContext.getPackageName(), SliceRenderActivity.class.getName());
607        return PendingIntent.getActivity(mContext, 0, intent, 0);
608    }
609
610    private void assertEquivalent(androidx.slice.core.SliceAction desired,
611            androidx.slice.core.SliceAction actual) {
612        assertEquals(desired.getTitle(), actual.getTitle());
613        assertEquals(desired.getContentDescription(), actual.getContentDescription());
614        assertEquals(desired.isToggle(), actual.isToggle());
615        assertEquals(desired.isDefaultToggle(), actual.isDefaultToggle());
616        assertEquals(desired.isChecked(), actual.isChecked());
617        assertEquals(desired.getPriority(), actual.getPriority());
618        assertEquals(desired.getIcon() == null, actual.getIcon() == null);
619        assertEquals(desired.getImageMode(), actual.getImageMode());
620    }
621}
622