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