1/*
2 * Copyright (C) 2016 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 com.android.server.pm;
17
18import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertBundlesEqual;
19import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
20import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertWith;
21import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
22import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.makeBundle;
23import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.parceled;
24import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.set;
25
26import static org.mockito.Matchers.anyInt;
27import static org.mockito.Matchers.anyString;
28import static org.mockito.Matchers.eq;
29import static org.mockito.Mockito.reset;
30import static org.mockito.Mockito.times;
31import static org.mockito.Mockito.verify;
32
33import android.Manifest.permission;
34import android.app.ActivityManager;
35import android.content.ComponentName;
36import android.content.Intent;
37import android.content.pm.ShortcutInfo;
38import android.content.res.Resources;
39import android.graphics.BitmapFactory;
40import android.graphics.drawable.Icon;
41import android.net.Uri;
42import android.os.PersistableBundle;
43import android.os.UserHandle;
44import android.test.MoreAsserts;
45import android.test.suitebuilder.annotation.SmallTest;
46
47import com.android.frameworks.servicestests.R;
48import com.android.server.pm.ShortcutUser.PackageWithUser;
49
50import java.io.File;
51import java.io.FileWriter;
52import java.io.IOException;
53import java.io.PrintWriter;
54import java.io.StringWriter;
55import java.io.Writer;
56import java.util.Locale;
57
58/**
59 * Tests for ShortcutService and ShortcutManager.
60 *
61 m FrameworksServicesTests &&
62 adb install \
63 -r -g ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
64 adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \
65 -w com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
66 */
67@SmallTest
68public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
69    // ShortcutInfo tests
70
71    public void testShortcutInfoMissingMandatoryFields() {
72        // Disable throttling.
73        mService.updateConfigurationLocked(
74                ShortcutService.ConfigConstants.KEY_MAX_UPDATES_PER_INTERVAL + "=99999999,"
75                + ShortcutService.ConfigConstants.KEY_MAX_SHORTCUTS + "=99999999"
76        );
77
78        assertExpectException(
79                IllegalArgumentException.class,
80                "ID must be provided",
81                () -> new ShortcutInfo.Builder(getTestContext()).build());
82
83        assertExpectException(
84                RuntimeException.class,
85                "id cannot be empty",
86                () -> new ShortcutInfo.Builder(getTestContext(), null));
87
88        assertExpectException(
89                RuntimeException.class,
90                "id cannot be empty",
91                () -> new ShortcutInfo.Builder(getTestContext(), ""));
92
93        assertExpectException(
94                RuntimeException.class,
95                "intents cannot contain null",
96                () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(null));
97
98        assertExpectException(
99                RuntimeException.class,
100                "action must be set",
101                () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
102
103        assertExpectException(
104                RuntimeException.class,
105                "action must be set",
106                () -> new ShortcutInfo.Builder(getTestContext(), "id")
107                        .setIntents(new Intent[]{new Intent("action"), new Intent()}));
108
109        assertExpectException(
110                RuntimeException.class,
111                "activity cannot be null",
112                () -> new ShortcutInfo.Builder(getTestContext(), "id").setActivity(null));
113
114        assertExpectException(
115                RuntimeException.class,
116                "shortLabel cannot be empty",
117                () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(null));
118
119        assertExpectException(
120                RuntimeException.class,
121                "shortLabel cannot be empty",
122                () -> new ShortcutInfo.Builder(getTestContext(), "id").setShortLabel(""));
123
124        assertExpectException(
125                RuntimeException.class,
126                "longLabel cannot be empty",
127                () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(null));
128
129        assertExpectException(
130                RuntimeException.class,
131                "longLabel cannot be empty",
132                () -> new ShortcutInfo.Builder(getTestContext(), "id").setLongLabel(""));
133
134        assertExpectException(
135                RuntimeException.class,
136                "disabledMessage cannot be empty",
137                () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(null));
138
139        assertExpectException(
140                RuntimeException.class,
141                "disabledMessage cannot be empty",
142                () -> new ShortcutInfo.Builder(getTestContext(), "id").setDisabledMessage(""));
143
144        assertExpectException(NullPointerException.class, "action must be set",
145                () -> new ShortcutInfo.Builder(getTestContext(), "id").setIntent(new Intent()));
146
147        assertExpectException(
148                IllegalArgumentException.class, "Short label must be provided", () -> {
149            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
150                    .setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
151                    .build();
152            assertTrue(getManager().setDynamicShortcuts(list(si)));
153        });
154
155        // same for add.
156        assertExpectException(
157                IllegalArgumentException.class, "Short label must be provided", () -> {
158            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
159                    .setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
160                    .build();
161            assertTrue(getManager().addDynamicShortcuts(list(si)));
162        });
163
164        assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
165            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
166                    .setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
167                    .setShortLabel("x")
168                    .build();
169            assertTrue(getManager().setDynamicShortcuts(list(si)));
170        });
171
172        // same for add.
173        assertExpectException(NullPointerException.class, "Intent must be provided", () -> {
174            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
175                    .setActivity(new ComponentName(getTestContext().getPackageName(), "s"))
176                    .setShortLabel("x")
177                    .build();
178            assertTrue(getManager().addDynamicShortcuts(list(si)));
179        });
180
181        assertExpectException(
182                IllegalStateException.class, "does not belong to package", () -> {
183            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
184                    .setActivity(new ComponentName("xxx", "s"))
185                    .build();
186            assertTrue(getManager().setDynamicShortcuts(list(si)));
187        });
188
189        // same for add.
190        assertExpectException(
191                IllegalStateException.class, "does not belong to package", () -> {
192            ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
193                    .setActivity(new ComponentName("xxx", "s"))
194                    .build();
195            assertTrue(getManager().addDynamicShortcuts(list(si)));
196        });
197
198        // Now all activities are not main.
199        mMainActivityChecker = (component, userId) -> false;
200
201        assertExpectException(
202                IllegalStateException.class, "is not main", () -> {
203                    ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
204                            .setActivity(new ComponentName(getTestContext(), "s"))
205                            .build();
206                    assertTrue(getManager().setDynamicShortcuts(list(si)));
207                });
208        // For add
209        assertExpectException(
210                IllegalStateException.class, "is not main", () -> {
211                    ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
212                            .setActivity(new ComponentName(getTestContext(), "s"))
213                            .build();
214                    assertTrue(getManager().addDynamicShortcuts(list(si)));
215                });
216        // For update
217        assertExpectException(
218                IllegalStateException.class, "is not main", () -> {
219                    ShortcutInfo si = new ShortcutInfo.Builder(getTestContext(), "id")
220                            .setActivity(new ComponentName(getTestContext(), "s"))
221                            .build();
222                    assertTrue(getManager().updateShortcuts(list(si)));
223                });
224    }
225
226    public void testShortcutInfoParcel() {
227        setCaller(CALLING_PACKAGE_1, USER_10);
228        ShortcutInfo si = parceled(new ShortcutInfo.Builder(mClientContext)
229                .setId("id")
230                .setTitle("title")
231                .setIntent(makeIntent("action", ShortcutActivity.class))
232                .build());
233        assertEquals(mClientContext.getPackageName(), si.getPackage());
234        assertEquals(USER_10, si.getUserId());
235        assertEquals(HANDLE_USER_10, si.getUserHandle());
236        assertEquals("id", si.getId());
237        assertEquals("title", si.getTitle());
238        assertEquals("action", si.getIntent().getAction());
239
240        PersistableBundle pb = new PersistableBundle();
241        pb.putInt("k", 1);
242
243        si = new ShortcutInfo.Builder(getTestContext())
244                .setId("id")
245                .setActivity(new ComponentName("a", "b"))
246                .setIcon(Icon.createWithResource(mClientContext, 123))
247                .setTitle("title")
248                .setText("text")
249                .setDisabledMessage("dismes")
250                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
251                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
252                .setRank(123)
253                .setExtras(pb)
254                .build();
255        si.addFlags(ShortcutInfo.FLAG_PINNED);
256        si.setBitmapPath("abc");
257        si.setIconResourceId(456);
258
259        si = parceled(si);
260
261        assertEquals(getTestContext().getPackageName(), si.getPackage());
262        assertEquals("id", si.getId());
263        assertEquals(new ComponentName("a", "b"), si.getActivity());
264        assertEquals(123, si.getIcon().getResId());
265        assertEquals("title", si.getTitle());
266        assertEquals("text", si.getText());
267        assertEquals("dismes", si.getDisabledMessage());
268        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
269        assertEquals("action", si.getIntent().getAction());
270        assertEquals("val", si.getIntent().getStringExtra("key"));
271        assertEquals(123, si.getRank());
272        assertEquals(1, si.getExtras().getInt("k"));
273
274        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
275        assertEquals("abc", si.getBitmapPath());
276        assertEquals(456, si.getIconResourceId());
277
278        assertEquals(0, si.getTitleResId());
279        assertEquals(null, si.getTitleResName());
280        assertEquals(0, si.getTextResId());
281        assertEquals(null, si.getTextResName());
282        assertEquals(0, si.getDisabledMessageResourceId());
283        assertEquals(null, si.getDisabledMessageResName());
284    }
285
286    public void testShortcutInfoParcel_resId() {
287        setCaller(CALLING_PACKAGE_1, USER_10);
288        ShortcutInfo si;
289
290        PersistableBundle pb = new PersistableBundle();
291        pb.putInt("k", 1);
292
293        si = new ShortcutInfo.Builder(getTestContext())
294                .setId("id")
295                .setActivity(new ComponentName("a", "b"))
296                .setIcon(Icon.createWithResource(mClientContext, 123))
297                .setTitleResId(10)
298                .setTextResId(11)
299                .setDisabledMessageResId(12)
300                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
301                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
302                .setRank(123)
303                .setExtras(pb)
304                .build();
305        si.addFlags(ShortcutInfo.FLAG_PINNED);
306        si.setBitmapPath("abc");
307        si.setIconResourceId(456);
308
309        lookupAndFillInResourceNames(si);
310
311        si = parceled(si);
312
313        assertEquals(getTestContext().getPackageName(), si.getPackage());
314        assertEquals("id", si.getId());
315        assertEquals(new ComponentName("a", "b"), si.getActivity());
316        assertEquals(123, si.getIcon().getResId());
317        assertEquals(10, si.getTitleResId());
318        assertEquals("r10", si.getTitleResName());
319        assertEquals(11, si.getTextResId());
320        assertEquals("r11", si.getTextResName());
321        assertEquals(12, si.getDisabledMessageResourceId());
322        assertEquals("r12", si.getDisabledMessageResName());
323        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
324        assertEquals("action", si.getIntent().getAction());
325        assertEquals("val", si.getIntent().getStringExtra("key"));
326        assertEquals(123, si.getRank());
327        assertEquals(1, si.getExtras().getInt("k"));
328
329        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
330        assertEquals("abc", si.getBitmapPath());
331        assertEquals(456, si.getIconResourceId());
332        assertEquals("string/r456", si.getIconResName());
333    }
334
335    public void testShortcutInfoClone() {
336        setCaller(CALLING_PACKAGE_1, USER_11);
337
338        PersistableBundle pb = new PersistableBundle();
339        pb.putInt("k", 1);
340        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
341                .setId("id")
342                .setActivity(new ComponentName("a", "b"))
343                .setIcon(Icon.createWithResource(mClientContext, 123))
344                .setTitle("title")
345                .setText("text")
346                .setDisabledMessage("dismes")
347                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
348                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
349                .setRank(123)
350                .setExtras(pb)
351                .build();
352        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
353        sorig.setBitmapPath("abc");
354        sorig.setIconResourceId(456);
355
356        lookupAndFillInResourceNames(sorig);
357
358        ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
359
360        assertEquals(USER_11, si.getUserId());
361        assertEquals(HANDLE_USER_11, si.getUserHandle());
362        assertEquals(mClientContext.getPackageName(), si.getPackage());
363        assertEquals("id", si.getId());
364        assertEquals(new ComponentName("a", "b"), si.getActivity());
365        assertEquals(123, si.getIcon().getResId());
366        assertEquals("title", si.getTitle());
367        assertEquals("text", si.getText());
368        assertEquals("dismes", si.getDisabledMessage());
369        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
370        assertEquals("action", si.getIntent().getAction());
371        assertEquals("val", si.getIntent().getStringExtra("key"));
372        assertEquals(123, si.getRank());
373        assertEquals(1, si.getExtras().getInt("k"));
374
375        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
376        assertEquals("abc", si.getBitmapPath());
377        assertEquals(456, si.getIconResourceId());
378        assertEquals("string/r456", si.getIconResName());
379
380        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
381
382        assertEquals(mClientContext.getPackageName(), si.getPackage());
383        assertEquals("id", si.getId());
384        assertEquals(new ComponentName("a", "b"), si.getActivity());
385        assertEquals(null, si.getIcon());
386        assertEquals("title", si.getTitle());
387        assertEquals("text", si.getText());
388        assertEquals("dismes", si.getDisabledMessage());
389        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
390        assertEquals("action", si.getIntent().getAction());
391        assertEquals("val", si.getIntent().getStringExtra("key"));
392        assertEquals(123, si.getRank());
393        assertEquals(1, si.getExtras().getInt("k"));
394
395        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
396        assertEquals(null, si.getBitmapPath());
397
398        assertEquals(456, si.getIconResourceId());
399        assertEquals(null, si.getIconResName());
400
401        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
402
403        assertEquals(mClientContext.getPackageName(), si.getPackage());
404        assertEquals("id", si.getId());
405        assertEquals(new ComponentName("a", "b"), si.getActivity());
406        assertEquals(null, si.getIcon());
407        assertEquals("title", si.getTitle());
408        assertEquals("text", si.getText());
409        assertEquals("dismes", si.getDisabledMessage());
410        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
411        assertEquals(null, si.getIntent());
412        assertEquals(123, si.getRank());
413        assertEquals(1, si.getExtras().getInt("k"));
414
415        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
416        assertEquals(null, si.getBitmapPath());
417
418        assertEquals(456, si.getIconResourceId());
419        assertEquals(null, si.getIconResName());
420
421        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
422
423        assertEquals(mClientContext.getPackageName(), si.getPackage());
424        assertEquals("id", si.getId());
425        assertEquals(new ComponentName("a", "b"), si.getActivity());
426        assertEquals(null, si.getIcon());
427        assertEquals(null, si.getTitle());
428        assertEquals(null, si.getText());
429        assertEquals(null, si.getDisabledMessage());
430        assertEquals(null, si.getCategories());
431        assertEquals(null, si.getIntent());
432        assertEquals(0, si.getRank());
433        assertEquals(null, si.getExtras());
434
435        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
436        assertEquals(null, si.getBitmapPath());
437
438        assertEquals(456, si.getIconResourceId());
439        assertEquals(null, si.getIconResName());
440    }
441
442    public void testShortcutInfoClone_resId() {
443        setCaller(CALLING_PACKAGE_1, USER_11);
444
445        PersistableBundle pb = new PersistableBundle();
446        pb.putInt("k", 1);
447        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
448                .setId("id")
449                .setActivity(new ComponentName("a", "b"))
450                .setIcon(Icon.createWithResource(mClientContext, 123))
451                .setTitleResId(10)
452                .setTextResId(11)
453                .setDisabledMessageResId(12)
454                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
455                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
456                .setRank(123)
457                .setExtras(pb)
458                .build();
459        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
460        sorig.setBitmapPath("abc");
461        sorig.setIconResourceId(456);
462
463        lookupAndFillInResourceNames(sorig);
464
465        ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
466
467        assertEquals(USER_11, si.getUserId());
468        assertEquals(HANDLE_USER_11, si.getUserHandle());
469        assertEquals(mClientContext.getPackageName(), si.getPackage());
470        assertEquals("id", si.getId());
471        assertEquals(new ComponentName("a", "b"), si.getActivity());
472        assertEquals(123, si.getIcon().getResId());
473        assertEquals(10, si.getTitleResId());
474        assertEquals("r10", si.getTitleResName());
475        assertEquals(11, si.getTextResId());
476        assertEquals("r11", si.getTextResName());
477        assertEquals(12, si.getDisabledMessageResourceId());
478        assertEquals("r12", si.getDisabledMessageResName());
479        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
480        assertEquals("action", si.getIntent().getAction());
481        assertEquals("val", si.getIntent().getStringExtra("key"));
482        assertEquals(123, si.getRank());
483        assertEquals(1, si.getExtras().getInt("k"));
484
485        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
486        assertEquals("abc", si.getBitmapPath());
487        assertEquals(456, si.getIconResourceId());
488        assertEquals("string/r456", si.getIconResName());
489
490        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
491
492        assertEquals(mClientContext.getPackageName(), si.getPackage());
493        assertEquals("id", si.getId());
494        assertEquals(new ComponentName("a", "b"), si.getActivity());
495        assertEquals(null, si.getIcon());
496        assertEquals(10, si.getTitleResId());
497        assertEquals(null, si.getTitleResName());
498        assertEquals(11, si.getTextResId());
499        assertEquals(null, si.getTextResName());
500        assertEquals(12, si.getDisabledMessageResourceId());
501        assertEquals(null, si.getDisabledMessageResName());
502        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
503        assertEquals("action", si.getIntent().getAction());
504        assertEquals("val", si.getIntent().getStringExtra("key"));
505        assertEquals(123, si.getRank());
506        assertEquals(1, si.getExtras().getInt("k"));
507
508        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
509        assertEquals(null, si.getBitmapPath());
510
511        assertEquals(456, si.getIconResourceId());
512        assertEquals(null, si.getIconResName());
513
514        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
515
516        assertEquals(mClientContext.getPackageName(), si.getPackage());
517        assertEquals("id", si.getId());
518        assertEquals(new ComponentName("a", "b"), si.getActivity());
519        assertEquals(null, si.getIcon());
520        assertEquals(10, si.getTitleResId());
521        assertEquals(null, si.getTitleResName());
522        assertEquals(11, si.getTextResId());
523        assertEquals(null, si.getTextResName());
524        assertEquals(12, si.getDisabledMessageResourceId());
525        assertEquals(null, si.getDisabledMessageResName());
526        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
527        assertEquals(null, si.getIntent());
528        assertEquals(123, si.getRank());
529        assertEquals(1, si.getExtras().getInt("k"));
530
531        assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
532        assertEquals(null, si.getBitmapPath());
533
534        assertEquals(456, si.getIconResourceId());
535        assertEquals(null, si.getIconResName());
536
537        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
538
539        assertEquals(mClientContext.getPackageName(), si.getPackage());
540        assertEquals("id", si.getId());
541        assertEquals(new ComponentName("a", "b"), si.getActivity());
542        assertEquals(null, si.getIcon());
543        assertEquals(0, si.getTitleResId());
544        assertEquals(null, si.getTitleResName());
545        assertEquals(0, si.getTextResId());
546        assertEquals(null, si.getTextResName());
547        assertEquals(0, si.getDisabledMessageResourceId());
548        assertEquals(null, si.getDisabledMessageResName());
549        assertEquals(null, si.getCategories());
550        assertEquals(null, si.getIntent());
551        assertEquals(0, si.getRank());
552        assertEquals(null, si.getExtras());
553
554        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
555        assertEquals(null, si.getBitmapPath());
556
557        assertEquals(456, si.getIconResourceId());
558        assertEquals(null, si.getIconResName());
559    }
560
561    public void testShortcutInfoClone_minimum() {
562        PersistableBundle pb = new PersistableBundle();
563        pb.putInt("k", 1);
564        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
565                .setId("id")
566                .setTitle("title")
567                .setIntent(makeIntent("action", ShortcutActivity.class))
568                .build();
569        ShortcutInfo si = sorig.clone(/* clone flags*/ 0);
570
571        assertEquals(getTestContext().getPackageName(), si.getPackage());
572        assertEquals("id", si.getId());
573        assertEquals("title", si.getTitle());
574        assertEquals("action", si.getIntent().getAction());
575        assertEquals(null, si.getCategories());
576
577        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_CREATOR);
578
579        assertEquals(getTestContext().getPackageName(), si.getPackage());
580        assertEquals("id", si.getId());
581        assertEquals("title", si.getTitle());
582        assertEquals("action", si.getIntent().getAction());
583        assertEquals(null, si.getCategories());
584
585        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
586
587        assertEquals(getTestContext().getPackageName(), si.getPackage());
588        assertEquals("id", si.getId());
589        assertEquals("title", si.getTitle());
590        assertEquals(null, si.getIntent());
591        assertEquals(null, si.getCategories());
592
593        si = sorig.clone(ShortcutInfo.CLONE_REMOVE_NON_KEY_INFO);
594
595        assertEquals(getTestContext().getPackageName(), si.getPackage());
596        assertEquals("id", si.getId());
597        assertEquals(null, si.getTitle());
598        assertEquals(null, si.getIntent());
599        assertEquals(null, si.getCategories());
600    }
601
602    public void testShortcutInfoCopyNonNullFieldsFrom() throws InterruptedException {
603        PersistableBundle pb = new PersistableBundle();
604        pb.putInt("k", 1);
605        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
606                .setId("id")
607                .setActivity(new ComponentName("a", "b"))
608                .setIcon(Icon.createWithResource(mClientContext, 123))
609                .setTitle("title")
610                .setText("text")
611                .setDisabledMessage("dismes")
612                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
613                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
614                .setRank(123)
615                .setExtras(pb)
616                .build();
617        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
618        sorig.setBitmapPath("abc");
619        sorig.setIconResourceId(456);
620
621        lookupAndFillInResourceNames(sorig);
622
623        ShortcutInfo si;
624
625        si = sorig.clone(/* flags=*/ 0);
626        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
627                .setActivity(new ComponentName("x", "y")).build());
628        assertEquals("text", si.getText());
629        assertEquals(123, si.getRank());
630        assertEquals(new ComponentName("x", "y"), si.getActivity());
631
632        si = sorig.clone(/* flags=*/ 0);
633        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
634                .setIcon(Icon.createWithResource(mClientContext, 456)).build());
635        assertEquals("text", si.getText());
636        assertEquals(456, si.getIcon().getResId());
637        assertEquals(0, si.getIconResourceId());
638        assertEquals(null, si.getIconResName());
639        assertEquals(null, si.getBitmapPath());
640
641        si = sorig.clone(/* flags=*/ 0);
642        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
643                .setTitle("xyz").build());
644        assertEquals("text", si.getText());
645        assertEquals("xyz", si.getTitle());
646        assertEquals(0, si.getTitleResId());
647
648        si = sorig.clone(/* flags=*/ 0);
649        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
650                .setTitleResId(123).build());
651        assertEquals("text", si.getText());
652        assertEquals(null, si.getTitle());
653        assertEquals(123, si.getTitleResId());
654
655        si = sorig.clone(/* flags=*/ 0);
656        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
657                .setText("xxx").build());
658        assertEquals(123, si.getRank());
659        assertEquals("xxx", si.getText());
660        assertEquals(0, si.getTextResId());
661
662        si = sorig.clone(/* flags=*/ 0);
663        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
664                .setTextResId(1111).build());
665        assertEquals(123, si.getRank());
666        assertEquals(null, si.getText());
667        assertEquals(1111, si.getTextResId());
668
669        si = sorig.clone(/* flags=*/ 0);
670        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
671                .setDisabledMessage("xxx").build());
672        assertEquals(123, si.getRank());
673        assertEquals("xxx", si.getDisabledMessage());
674        assertEquals(0, si.getDisabledMessageResourceId());
675
676        si = sorig.clone(/* flags=*/ 0);
677        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
678                .setDisabledMessageResId(11111).build());
679        assertEquals(123, si.getRank());
680        assertEquals(null, si.getDisabledMessage());
681        assertEquals(11111, si.getDisabledMessageResourceId());
682
683        si = sorig.clone(/* flags=*/ 0);
684        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
685                .setCategories(set()).build());
686        assertEquals("text", si.getText());
687        assertEquals(set(), si.getCategories());
688
689        si = sorig.clone(/* flags=*/ 0);
690        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
691                .setCategories(set("x")).build());
692        assertEquals("text", si.getText());
693        assertEquals(set("x"), si.getCategories());
694
695        si = sorig.clone(/* flags=*/ 0);
696        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
697                .setIntent(makeIntent("action2", ShortcutActivity.class)).build());
698        assertEquals("text", si.getText());
699        assertEquals("action2", si.getIntent().getAction());
700        assertEquals(null, si.getIntent().getStringExtra("key"));
701
702        si = sorig.clone(/* flags=*/ 0);
703        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
704                .setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
705        assertEquals("text", si.getText());
706        assertEquals("action3", si.getIntent().getAction());
707        assertEquals("x", si.getIntent().getStringExtra("key"));
708
709        si = sorig.clone(/* flags=*/ 0);
710        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
711                .setRank(999).build());
712        assertEquals("text", si.getText());
713        assertEquals(999, si.getRank());
714
715
716        PersistableBundle pb2 = new PersistableBundle();
717        pb2.putInt("x", 99);
718
719        si = sorig.clone(/* flags=*/ 0);
720        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
721                .setExtras(pb2).build());
722        assertEquals("text", si.getText());
723        assertEquals(99, si.getExtras().getInt("x"));
724    }
725
726    public void testShortcutInfoCopyNonNullFieldsFrom_resId() throws InterruptedException {
727        PersistableBundle pb = new PersistableBundle();
728        pb.putInt("k", 1);
729        ShortcutInfo sorig = new ShortcutInfo.Builder(getTestContext())
730                .setId("id")
731                .setActivity(new ComponentName("a", "b"))
732                .setIcon(Icon.createWithResource(mClientContext, 123))
733                .setTitleResId(10)
734                .setTextResId(11)
735                .setDisabledMessageResId(12)
736                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
737                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
738                .setRank(123)
739                .setExtras(pb)
740                .build();
741        sorig.addFlags(ShortcutInfo.FLAG_PINNED);
742        sorig.setBitmapPath("abc");
743        sorig.setIconResourceId(456);
744
745        ShortcutInfo si;
746
747        si = sorig.clone(/* flags=*/ 0);
748        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
749                .setActivity(new ComponentName("x", "y")).build());
750        assertEquals(11, si.getTextResId());
751        assertEquals(new ComponentName("x", "y"), si.getActivity());
752
753        si = sorig.clone(/* flags=*/ 0);
754        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
755                .setIcon(Icon.createWithResource(mClientContext, 456)).build());
756        assertEquals(11, si.getTextResId());
757        assertEquals(456, si.getIcon().getResId());
758        assertEquals(0, si.getIconResourceId());
759        assertEquals(null, si.getIconResName());
760        assertEquals(null, si.getBitmapPath());
761
762        si = sorig.clone(/* flags=*/ 0);
763        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
764                .setTitle("xyz").build());
765        assertEquals(11, si.getTextResId());
766        assertEquals("xyz", si.getTitle());
767        assertEquals(0, si.getTitleResId());
768        assertEquals(null, si.getTitleResName());
769
770        si = sorig.clone(/* flags=*/ 0);
771        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
772                .setTitleResId(123).build());
773        assertEquals(11, si.getTextResId());
774        assertEquals(null, si.getTitle());
775        assertEquals(123, si.getTitleResId());
776        assertEquals(null, si.getTitleResName());
777
778        si = sorig.clone(/* flags=*/ 0);
779        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
780                .setText("xxx").build());
781        assertEquals(123, si.getRank());
782        assertEquals("xxx", si.getText());
783        assertEquals(0, si.getTextResId());
784        assertEquals(null, si.getTextResName());
785
786        si = sorig.clone(/* flags=*/ 0);
787        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
788                .setTextResId(1111).build());
789        assertEquals(123, si.getRank());
790        assertEquals(null, si.getText());
791        assertEquals(1111, si.getTextResId());
792        assertEquals(null, si.getTextResName());
793
794        si = sorig.clone(/* flags=*/ 0);
795        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
796                .setDisabledMessage("xxx").build());
797        assertEquals(123, si.getRank());
798        assertEquals("xxx", si.getDisabledMessage());
799        assertEquals(0, si.getDisabledMessageResourceId());
800        assertEquals(null, si.getDisabledMessageResName());
801
802        si = sorig.clone(/* flags=*/ 0);
803        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
804                .setDisabledMessageResId(11111).build());
805        assertEquals(123, si.getRank());
806        assertEquals(null, si.getDisabledMessage());
807        assertEquals(11111, si.getDisabledMessageResourceId());
808        assertEquals(null, si.getDisabledMessageResName());
809
810        si = sorig.clone(/* flags=*/ 0);
811        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
812                .setCategories(set()).build());
813        assertEquals(11, si.getTextResId());
814        assertEquals(set(), si.getCategories());
815
816        si = sorig.clone(/* flags=*/ 0);
817        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
818                .setCategories(set("x")).build());
819        assertEquals(11, si.getTextResId());
820        assertEquals(set("x"), si.getCategories());
821
822        si = sorig.clone(/* flags=*/ 0);
823        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
824                .setIntent(makeIntent("action2", ShortcutActivity.class)).build());
825        assertEquals(11, si.getTextResId());
826        assertEquals("action2", si.getIntent().getAction());
827        assertEquals(null, si.getIntent().getStringExtra("key"));
828
829        si = sorig.clone(/* flags=*/ 0);
830        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
831                .setIntent(makeIntent("action3", ShortcutActivity.class, "key", "x")).build());
832        assertEquals(11, si.getTextResId());
833        assertEquals("action3", si.getIntent().getAction());
834        assertEquals("x", si.getIntent().getStringExtra("key"));
835
836        si = sorig.clone(/* flags=*/ 0);
837        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
838                .setRank(999).build());
839        assertEquals(11, si.getTextResId());
840        assertEquals(999, si.getRank());
841
842
843        PersistableBundle pb2 = new PersistableBundle();
844        pb2.putInt("x", 99);
845
846        si = sorig.clone(/* flags=*/ 0);
847        si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
848                .setExtras(pb2).build());
849        assertEquals(11, si.getTextResId());
850        assertEquals(99, si.getExtras().getInt("x"));
851    }
852
853    public void testShortcutInfoSaveAndLoad() throws InterruptedException {
854        mRunningUsers.put(USER_10, true);
855
856        setCaller(CALLING_PACKAGE_1, USER_10);
857
858        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
859                getTestContext().getResources(), R.drawable.black_32x32));
860
861        PersistableBundle pb = new PersistableBundle();
862        pb.putInt("k", 1);
863        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
864                .setId("id")
865                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
866                .setIcon(bmp32x32)
867                .setTitle("title")
868                .setText("text")
869                .setDisabledMessage("dismes")
870                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
871                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
872                .setRank(123)
873                .setExtras(pb)
874                .build();
875        sorig.setTimestamp(mInjectedCurrentTimeMillis);
876
877        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
878                .setId("id2")
879                .setTitle("x")
880                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
881                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
882                .setRank(456)
883                .build();
884        sorig2.setTimestamp(mInjectedCurrentTimeMillis);
885
886        mManager.addDynamicShortcuts(list(sorig, sorig2));
887
888        mInjectedCurrentTimeMillis += 1;
889        final long now = mInjectedCurrentTimeMillis;
890        mInjectedCurrentTimeMillis += 1;
891
892        dumpsysOnLogcat("before save");
893
894        // Save and load.
895        mService.saveDirtyInfo();
896        initService();
897        mService.handleUnlockUser(USER_10);
898
899        dumpUserFile(USER_10);
900        dumpsysOnLogcat("after load");
901
902        ShortcutInfo si;
903        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
904
905        assertEquals(USER_10, si.getUserId());
906        assertEquals(HANDLE_USER_10, si.getUserHandle());
907        assertEquals(CALLING_PACKAGE_1, si.getPackage());
908        assertEquals("id", si.getId());
909        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
910        assertEquals(null, si.getIcon());
911        assertEquals("title", si.getTitle());
912        assertEquals("text", si.getText());
913        assertEquals("dismes", si.getDisabledMessage());
914        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
915        assertEquals("action", si.getIntent().getAction());
916        assertEquals("val", si.getIntent().getStringExtra("key"));
917        assertEquals(0, si.getRank());
918        assertEquals(1, si.getExtras().getInt("k"));
919
920        assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE
921                | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
922        assertNotNull(si.getBitmapPath()); // Something should be set.
923        assertEquals(0, si.getIconResourceId());
924        assertTrue(si.getLastChangedTimestamp() < now);
925
926        // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
927        // to test it.
928        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
929        assertEquals(1, si.getRank());
930
931        dumpUserFile(USER_10);
932    }
933
934    public void testShortcutInfoSaveAndLoad_maskableBitmap() throws InterruptedException {
935        mRunningUsers.put(USER_10, true);
936
937        setCaller(CALLING_PACKAGE_1, USER_10);
938
939        final Icon bmp32x32 = Icon.createWithAdaptiveBitmap(BitmapFactory.decodeResource(
940            getTestContext().getResources(), R.drawable.black_32x32));
941
942        PersistableBundle pb = new PersistableBundle();
943        pb.putInt("k", 1);
944        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
945            .setId("id")
946            .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
947            .setIcon(bmp32x32)
948            .setTitle("title")
949            .setText("text")
950            .setDisabledMessage("dismes")
951            .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
952            .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
953            .setRank(123)
954            .setExtras(pb)
955            .build();
956        sorig.setTimestamp(mInjectedCurrentTimeMillis);
957
958        mManager.addDynamicShortcuts(list(sorig));
959
960        mInjectedCurrentTimeMillis += 1;
961        final long now = mInjectedCurrentTimeMillis;
962        mInjectedCurrentTimeMillis += 1;
963
964        dumpsysOnLogcat("before save");
965
966        // Save and load.
967        mService.saveDirtyInfo();
968        initService();
969        mService.handleUnlockUser(USER_10);
970
971        dumpUserFile(USER_10);
972        dumpsysOnLogcat("after load");
973
974        ShortcutInfo si;
975        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
976
977        assertEquals(USER_10, si.getUserId());
978        assertEquals(HANDLE_USER_10, si.getUserHandle());
979        assertEquals(CALLING_PACKAGE_1, si.getPackage());
980        assertEquals("id", si.getId());
981        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
982        assertEquals(null, si.getIcon());
983        assertEquals("title", si.getTitle());
984        assertEquals("text", si.getText());
985        assertEquals("dismes", si.getDisabledMessage());
986        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
987        assertEquals("action", si.getIntent().getAction());
988        assertEquals("val", si.getIntent().getStringExtra("key"));
989        assertEquals(0, si.getRank());
990        assertEquals(1, si.getExtras().getInt("k"));
991
992        assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_FILE
993            | ShortcutInfo.FLAG_STRINGS_RESOLVED | ShortcutInfo.FLAG_ADAPTIVE_BITMAP,
994            si.getFlags());
995        assertNotNull(si.getBitmapPath()); // Something should be set.
996        assertEquals(0, si.getIconResourceId());
997        assertTrue(si.getLastChangedTimestamp() < now);
998
999        dumpUserFile(USER_10);
1000    }
1001
1002    public void testShortcutInfoSaveAndLoad_resId() throws InterruptedException {
1003        mRunningUsers.put(USER_10, true);
1004
1005        setCaller(CALLING_PACKAGE_1, USER_10);
1006
1007        final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32);
1008
1009        PersistableBundle pb = new PersistableBundle();
1010        pb.putInt("k", 1);
1011        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
1012                .setId("id")
1013                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1014                .setIcon(res32x32)
1015                .setTitleResId(10)
1016                .setTextResId(11)
1017                .setDisabledMessageResId(12)
1018                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
1019                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1020                .setRank(123)
1021                .setExtras(pb)
1022                .build();
1023        sorig.setTimestamp(mInjectedCurrentTimeMillis);
1024
1025        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
1026                .setId("id2")
1027                .setTitle("x")
1028                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1029                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1030                .setRank(456)
1031                .build();
1032        sorig2.setTimestamp(mInjectedCurrentTimeMillis);
1033
1034        mManager.addDynamicShortcuts(list(sorig, sorig2));
1035
1036        mInjectedCurrentTimeMillis += 1;
1037        final long now = mInjectedCurrentTimeMillis;
1038        mInjectedCurrentTimeMillis += 1;
1039
1040        // Save and load.
1041        mService.saveDirtyInfo();
1042        initService();
1043        mService.handleUnlockUser(USER_10);
1044
1045        ShortcutInfo si;
1046        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_10);
1047
1048        assertEquals(USER_10, si.getUserId());
1049        assertEquals(HANDLE_USER_10, si.getUserHandle());
1050        assertEquals(CALLING_PACKAGE_1, si.getPackage());
1051        assertEquals("id", si.getId());
1052        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
1053        assertEquals(null, si.getIcon());
1054        assertEquals(10, si.getTitleResId());
1055        assertEquals("r10", si.getTitleResName());
1056        assertEquals(11, si.getTextResId());
1057        assertEquals("r11", si.getTextResName());
1058        assertEquals(12, si.getDisabledMessageResourceId());
1059        assertEquals("r12", si.getDisabledMessageResName());
1060        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
1061        assertEquals("action", si.getIntent().getAction());
1062        assertEquals("val", si.getIntent().getStringExtra("key"));
1063        assertEquals(0, si.getRank());
1064        assertEquals(1, si.getExtras().getInt("k"));
1065
1066        assertEquals(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_HAS_ICON_RES
1067                | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
1068        assertNull(si.getBitmapPath());
1069        assertEquals(R.drawable.black_32x32, si.getIconResourceId());
1070        assertTrue(si.getLastChangedTimestamp() < now);
1071
1072        // Make sure ranks are saved too.  Because of the auto-adjusting, we need two shortcuts
1073        // to test it.
1074        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_10);
1075        assertEquals(1, si.getRank());
1076    }
1077
1078    public void testShortcutInfoSaveAndLoad_forBackup() {
1079        setCaller(CALLING_PACKAGE_1, USER_0);
1080
1081        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
1082                getTestContext().getResources(), R.drawable.black_32x32));
1083
1084        PersistableBundle pb = new PersistableBundle();
1085        pb.putInt("k", 1);
1086        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
1087                .setId("id")
1088                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1089                .setIcon(bmp32x32)
1090                .setTitle("title")
1091                .setText("text")
1092                .setDisabledMessage("dismes")
1093                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
1094                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1095                .setRank(123)
1096                .setExtras(pb)
1097                .build();
1098
1099        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
1100                .setId("id2")
1101                .setTitle("x")
1102                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1103                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1104                .setRank(456)
1105                .build();
1106
1107        mManager.addDynamicShortcuts(list(sorig, sorig2));
1108
1109        // Dynamic shortcuts won't be backed up, so we need to pin it.
1110        setCaller(LAUNCHER_1, USER_0);
1111        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
1112
1113        // Do backup & restore.
1114        backupAndRestore();
1115
1116        mService.handleUnlockUser(USER_0); // Load user-0.
1117
1118        ShortcutInfo si;
1119        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
1120
1121        assertEquals(CALLING_PACKAGE_1, si.getPackage());
1122        assertEquals("id", si.getId());
1123        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
1124        assertEquals(null, si.getIcon());
1125        assertEquals("title", si.getTitle());
1126        assertEquals("text", si.getText());
1127        assertEquals("dismes", si.getDisabledMessage());
1128        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
1129        assertEquals("action", si.getIntent().getAction());
1130        assertEquals("val", si.getIntent().getStringExtra("key"));
1131        assertEquals(0, si.getRank());
1132        assertEquals(1, si.getExtras().getInt("k"));
1133
1134        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
1135        assertNull(si.getBitmapPath()); // No icon.
1136        assertEquals(0, si.getIconResourceId());
1137
1138        // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
1139        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
1140        assertEquals(0, si.getRank());
1141    }
1142
1143    public void testShortcutInfoSaveAndLoad_forBackup_resId() {
1144        setCaller(CALLING_PACKAGE_1, USER_0);
1145
1146        final Icon res32x32 = Icon.createWithResource(mClientContext, R.drawable.black_32x32);
1147
1148        PersistableBundle pb = new PersistableBundle();
1149        pb.putInt("k", 1);
1150        ShortcutInfo sorig = new ShortcutInfo.Builder(mClientContext)
1151                .setId("id")
1152                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1153                .setIcon(res32x32)
1154                .setTitleResId(10)
1155                .setTextResId(11)
1156                .setDisabledMessageResId(12)
1157                .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
1158                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1159                .setRank(123)
1160                .setExtras(pb)
1161                .build();
1162
1163        ShortcutInfo sorig2 = new ShortcutInfo.Builder(mClientContext)
1164                .setId("id2")
1165                .setTitle("x")
1166                .setActivity(new ComponentName(mClientContext, ShortcutActivity2.class))
1167                .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
1168                .setRank(456)
1169                .build();
1170
1171        mManager.addDynamicShortcuts(list(sorig, sorig2));
1172
1173        // Dynamic shortcuts won't be backed up, so we need to pin it.
1174        setCaller(LAUNCHER_1, USER_0);
1175        mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("id", "id2"), HANDLE_USER_0);
1176
1177        // Do backup & restore.
1178        backupAndRestore();
1179
1180        mService.handleUnlockUser(USER_0); // Load user-0.
1181
1182        ShortcutInfo si;
1183        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id", USER_0);
1184
1185        assertEquals(CALLING_PACKAGE_1, si.getPackage());
1186        assertEquals("id", si.getId());
1187        assertEquals(ShortcutActivity2.class.getName(), si.getActivity().getClassName());
1188        assertEquals(null, si.getIcon());
1189        assertEquals(10, si.getTitleResId());
1190        assertEquals("r10", si.getTitleResName());
1191        assertEquals(11, si.getTextResId());
1192        assertEquals("r11", si.getTextResName());
1193        assertEquals(12, si.getDisabledMessageResourceId());
1194        assertEquals("r12", si.getDisabledMessageResName());
1195        assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
1196        assertEquals("action", si.getIntent().getAction());
1197        assertEquals("val", si.getIntent().getStringExtra("key"));
1198        assertEquals(0, si.getRank());
1199        assertEquals(1, si.getExtras().getInt("k"));
1200
1201        assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_STRINGS_RESOLVED, si.getFlags());
1202        assertNull(si.getBitmapPath()); // No icon.
1203        assertEquals(0, si.getIconResourceId());
1204        assertEquals(null, si.getIconResName());
1205
1206        // Note when restored from backup, it's no longer dynamic, so shouldn't have a rank.
1207        si = mService.getPackageShortcutForTest(CALLING_PACKAGE_1, "id2", USER_0);
1208        assertEquals(0, si.getRank());
1209    }
1210
1211    private void checkShortcutInfoSaveAndLoad_intents(Intent intent) {
1212        assertTrue(mManager.setDynamicShortcuts(list(
1213                makeShortcutWithIntent("s1", intent))));
1214        initService();
1215        mService.handleUnlockUser(USER_0);
1216
1217        assertWith(getCallerShortcuts())
1218                .haveIds("s1")
1219                .forShortcutWithId("s1", si -> {
1220                    assertEquals(intent.getAction(), si.getIntent().getAction());
1221                    assertEquals(intent.getData(), si.getIntent().getData());
1222                    assertEquals(intent.getComponent(), si.getIntent().getComponent());
1223                    assertBundlesEqual(intent.getExtras(), si.getIntent().getExtras());
1224                });
1225    }
1226
1227    private void checkShortcutInfoSaveAndLoad_intents(Intent... intents) {
1228        assertTrue(mManager.setDynamicShortcuts(list(
1229                makeShortcutWithIntents("s1", intents))));
1230        initService();
1231        mService.handleUnlockUser(USER_0);
1232
1233        assertWith(getCallerShortcuts())
1234                .haveIds("s1")
1235                .forShortcutWithId("s1", si -> {
1236
1237                    final Intent[] actual = si.getIntents();
1238                    assertEquals(intents.length, actual.length);
1239
1240                    for (int i = 0; i < intents.length; i++) {
1241                        assertEquals(intents[i].getAction(), actual[i].getAction());
1242                        assertEquals(intents[i].getData(), actual[i].getData());
1243                        assertEquals(intents[i].getComponent(), actual[i].getComponent());
1244                        assertEquals(intents[i].getFlags(), actual[i].getFlags());
1245                        assertBundlesEqual(intents[i].getExtras(), actual[i].getExtras());
1246                    }
1247                });
1248    }
1249
1250    public void testShortcutInfoSaveAndLoad_intents() {
1251        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW));
1252
1253        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1254
1255        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN));
1256
1257        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1258
1259        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW,
1260                Uri.parse("http://www.example.com/")));
1261
1262        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1263
1264        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN,
1265                Uri.parse("http://www.example.com/")));
1266
1267        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1268
1269        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW)
1270                .setComponent(new ComponentName("a", "b")));
1271
1272        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1273
1274        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN)
1275                .setComponent(new ComponentName("a", "b")));
1276
1277        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1278
1279        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_VIEW)
1280                .putExtras(makeBundle("a", "b")));
1281
1282        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1283
1284
1285        checkShortcutInfoSaveAndLoad_intents(new Intent(Intent.ACTION_MAIN)
1286                .putExtras(makeBundle("a", "b")));
1287
1288        mInjectedCurrentTimeMillis += INTERVAL; // reset throttling.
1289
1290        // Multi-intents
1291        checkShortcutInfoSaveAndLoad_intents(
1292                new Intent(Intent.ACTION_MAIN).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK),
1293                new Intent(Intent.ACTION_VIEW).setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
1294        );
1295
1296        checkShortcutInfoSaveAndLoad_intents(
1297                new Intent(Intent.ACTION_MAIN).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
1298                        .setComponent(new ComponentName("a", "b")),
1299                new Intent(Intent.ACTION_VIEW)
1300                        .setComponent(new ComponentName("a", "b"))
1301                );
1302
1303        checkShortcutInfoSaveAndLoad_intents(
1304                new Intent(Intent.ACTION_MAIN)
1305                        .setComponent(new ComponentName("a", "b")),
1306                new Intent(Intent.ACTION_VIEW).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
1307                        .setComponent(new ComponentName("a", "b")),
1308                new Intent("xyz").setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
1309                        | Intent.FILL_IN_COMPONENT)
1310                        .setComponent(new ComponentName("a", "b")).putExtras(
1311                        makeBundle("xx", "yy"))
1312                );
1313    }
1314
1315    public void testThrottling() {
1316        final ShortcutInfo si1 = makeShortcut("shortcut1");
1317
1318        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1319        assertEquals(2, mManager.getRemainingCallCount());
1320        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1321
1322        mInjectedCurrentTimeMillis++;
1323        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1324        assertEquals(1, mManager.getRemainingCallCount());
1325        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1326
1327        mInjectedCurrentTimeMillis++;
1328        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1329        assertEquals(0, mManager.getRemainingCallCount());
1330        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1331
1332        // Reached the max
1333
1334        mInjectedCurrentTimeMillis++;
1335        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1336        assertEquals(0, mManager.getRemainingCallCount());
1337        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1338
1339        // Still throttled
1340        mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
1341        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1342        assertEquals(0, mManager.getRemainingCallCount());
1343        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1344
1345        // Now it should work.
1346        mInjectedCurrentTimeMillis++;
1347        assertTrue(mManager.setDynamicShortcuts(list(si1))); // fail
1348        assertEquals(2, mManager.getRemainingCallCount());
1349        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
1350
1351        mInjectedCurrentTimeMillis++;
1352        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1353        assertEquals(1, mManager.getRemainingCallCount());
1354        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
1355
1356        mInjectedCurrentTimeMillis++;
1357        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1358        assertEquals(0, mManager.getRemainingCallCount());
1359        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
1360
1361        mInjectedCurrentTimeMillis++;
1362        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1363        assertEquals(0, mManager.getRemainingCallCount());
1364        assertEquals(START_TIME + INTERVAL * 2, mManager.getRateLimitResetTime());
1365
1366        // 4 hours later...
1367        mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL;
1368        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1369        assertEquals(2, mManager.getRemainingCallCount());
1370        assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
1371
1372        mInjectedCurrentTimeMillis++;
1373        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1374        assertEquals(1, mManager.getRemainingCallCount());
1375        assertEquals(START_TIME + INTERVAL * 5, mManager.getRateLimitResetTime());
1376
1377        // Make sure getRemainingCallCount() itself gets reset without calling setDynamicShortcuts().
1378        mInjectedCurrentTimeMillis = START_TIME + 8 * INTERVAL;
1379        assertEquals(3, mManager.getRemainingCallCount());
1380        assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
1381
1382        mInjectedCurrentTimeMillis++;
1383        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1384        assertEquals(2, mManager.getRemainingCallCount());
1385        assertEquals(START_TIME + INTERVAL * 9, mManager.getRateLimitResetTime());
1386    }
1387
1388    public void testThrottling_rewind() {
1389        final ShortcutInfo si1 = makeShortcut("shortcut1");
1390
1391        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1392        assertEquals(2, mManager.getRemainingCallCount());
1393        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1394
1395        mInjectedCurrentTimeMillis = 12345; // Clock reset!
1396
1397        // Since the clock looks invalid, the counter shouldn't have reset.
1398        assertEquals(2, mManager.getRemainingCallCount());
1399        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1400
1401        // Forward again.  Still haven't reset yet.
1402        mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
1403        assertEquals(2, mManager.getRemainingCallCount());
1404        assertEquals(START_TIME + INTERVAL, mManager.getRateLimitResetTime());
1405
1406        // Now rewind -- this will reset the counters.
1407        mInjectedCurrentTimeMillis = START_TIME - 100000;
1408        assertEquals(3, mManager.getRemainingCallCount());
1409
1410        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1411        assertEquals(2, mManager.getRemainingCallCount());
1412
1413        // Forward again, should be reset now.
1414        mInjectedCurrentTimeMillis += INTERVAL;
1415        assertEquals(3, mManager.getRemainingCallCount());
1416    }
1417
1418    public void testThrottling_perPackage() {
1419        final ShortcutInfo si1 = makeShortcut("shortcut1");
1420
1421        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1422        assertEquals(2, mManager.getRemainingCallCount());
1423
1424        mInjectedCurrentTimeMillis++;
1425        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1426        assertEquals(1, mManager.getRemainingCallCount());
1427
1428        mInjectedCurrentTimeMillis++;
1429        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1430        assertEquals(0, mManager.getRemainingCallCount());
1431
1432        // Reached the max
1433
1434        mInjectedCurrentTimeMillis++;
1435        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1436
1437        // Try from a different caller.
1438        mInjectedClientPackage = CALLING_PACKAGE_2;
1439        mInjectedCallingUid = CALLING_UID_2;
1440
1441        // Need to create a new one wit the updated package name.
1442        final ShortcutInfo si2 = makeShortcut("shortcut1");
1443
1444        assertEquals(3, mManager.getRemainingCallCount());
1445
1446        assertTrue(mManager.setDynamicShortcuts(list(si2)));
1447        assertEquals(2, mManager.getRemainingCallCount());
1448
1449        mInjectedCurrentTimeMillis++;
1450        assertTrue(mManager.setDynamicShortcuts(list(si2)));
1451        assertEquals(1, mManager.getRemainingCallCount());
1452
1453        // Back to the original caller, still throttled.
1454        mInjectedClientPackage = CALLING_PACKAGE_1;
1455        mInjectedCallingUid = CALLING_UID_1;
1456
1457        mInjectedCurrentTimeMillis = START_TIME + INTERVAL - 1;
1458        assertEquals(0, mManager.getRemainingCallCount());
1459        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1460        assertEquals(0, mManager.getRemainingCallCount());
1461
1462        // Now it should work.
1463        mInjectedCurrentTimeMillis++;
1464        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1465
1466        mInjectedCurrentTimeMillis++;
1467        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1468
1469        mInjectedCurrentTimeMillis++;
1470        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1471
1472        mInjectedCurrentTimeMillis++;
1473        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1474
1475        mInjectedCurrentTimeMillis = START_TIME + 4 * INTERVAL;
1476        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1477        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1478        assertTrue(mManager.setDynamicShortcuts(list(si1)));
1479        assertFalse(mManager.setDynamicShortcuts(list(si1)));
1480
1481        mInjectedClientPackage = CALLING_PACKAGE_2;
1482        mInjectedCallingUid = CALLING_UID_2;
1483
1484        assertEquals(3, mManager.getRemainingCallCount());
1485
1486        assertTrue(mManager.setDynamicShortcuts(list(si2)));
1487        assertTrue(mManager.setDynamicShortcuts(list(si2)));
1488        assertTrue(mManager.setDynamicShortcuts(list(si2)));
1489        assertFalse(mManager.setDynamicShortcuts(list(si2)));
1490    }
1491
1492    public void testThrottling_localeChanges() {
1493        prepareCrossProfileDataSet();
1494
1495        dumpsysOnLogcat("Before save & load");
1496
1497        mService.saveDirtyInfo();
1498        initService();
1499
1500        mInjectedLocale = Locale.CHINA;
1501        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
1502
1503        // Note at this point only user-0 is loaded, and the counters are reset for this user,
1504        // but it will work for other users too because we check the locale change at any
1505        // API entry point.
1506
1507        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1508            assertEquals(3, mManager.getRemainingCallCount());
1509        });
1510        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1511            assertEquals(3, mManager.getRemainingCallCount());
1512        });
1513        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1514            assertEquals(3, mManager.getRemainingCallCount());
1515        });
1516        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1517            assertEquals(3, mManager.getRemainingCallCount());
1518        });
1519        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1520            assertEquals(3, mManager.getRemainingCallCount());
1521        });
1522        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1523            assertEquals(3, mManager.getRemainingCallCount());
1524        });
1525
1526        // Make sure even if we receive ACTION_LOCALE_CHANGED, if the locale hasn't actually
1527        // changed, we don't reset throttling.
1528        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1529            mManager.updateShortcuts(list());
1530            assertEquals(2, mManager.getRemainingCallCount());
1531        });
1532
1533        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
1534
1535        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1536            assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
1537        });
1538
1539        mService.saveDirtyInfo();
1540        initService();
1541
1542        // The locale should be persisted, so it still shouldn't reset throttling.
1543        mService.mReceiver.onReceive(mServiceContext, new Intent(Intent.ACTION_LOCALE_CHANGED));
1544
1545        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1546            assertEquals(2, mManager.getRemainingCallCount()); // Still 2.
1547        });
1548    }
1549
1550    public void testThrottling_foreground() throws Exception {
1551        prepareCrossProfileDataSet();
1552
1553        dumpsysOnLogcat("Before save & load");
1554
1555        mService.saveDirtyInfo();
1556        initService();
1557
1558        // We need to update the current time from time to time, since some of the internal checks
1559        // rely on the time being correctly incremented.
1560        mInjectedCurrentTimeMillis++;
1561
1562        // First, all packages have less than 3 (== initial value) remaining calls.
1563
1564        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1565            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1566        });
1567        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1568            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1569        });
1570        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1571            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1572        });
1573        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1574            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1575        });
1576        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1577            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1578        });
1579        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1580            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1581        });
1582
1583        mInjectedCurrentTimeMillis++;
1584
1585        // State changed, but not foreground, so no resetting.
1586        mService.mUidObserver.onUidStateChanged(
1587                CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
1588        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1589            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1590        });
1591        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1592            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1593        });
1594        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1595            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1596        });
1597        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1598            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1599        });
1600        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1601            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1602        });
1603        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1604            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1605        });
1606
1607        mInjectedCurrentTimeMillis++;
1608
1609        // State changed, package1 foreground, reset.
1610        mService.mUidObserver.onUidStateChanged(
1611                CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
1612        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1613            assertEquals(3, mManager.getRemainingCallCount());
1614        });
1615        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1616            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1617        });
1618        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1619            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1620        });
1621        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1622            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1623        });
1624        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1625            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1626        });
1627        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1628            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1629        });
1630        mService.mUidObserver.onUidStateChanged(
1631                CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
1632
1633        mInjectedCurrentTimeMillis++;
1634
1635        // Different app comes to foreground briefly, and goes back to background.
1636        // Now, make sure package 2's counter is reset, even in this case.
1637        mService.mUidObserver.onUidStateChanged(
1638                CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
1639        mService.mUidObserver.onUidStateChanged(
1640                CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
1641
1642        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1643            assertEquals(3, mManager.getRemainingCallCount());
1644        });
1645        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1646            assertEquals(3, mManager.getRemainingCallCount());
1647        });
1648        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1649            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1650        });
1651        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1652            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1653        });
1654        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1655            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1656        });
1657        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1658            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1659        });
1660
1661        mInjectedCurrentTimeMillis++;
1662
1663        // Do the same thing one more time.  This would catch the bug with mixuing up
1664        // the current time and the elapsed time.
1665        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1666            mManager.updateShortcuts(list(makeShortcut("s")));
1667            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1668        });
1669
1670        mService.mUidObserver.onUidStateChanged(
1671                CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
1672        mService.mUidObserver.onUidStateChanged(
1673                CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
1674
1675        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1676            assertEquals(3, mManager.getRemainingCallCount());
1677        });
1678        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1679            assertEquals(3, mManager.getRemainingCallCount());
1680        });
1681        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1682            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1683        });
1684        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1685            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1686        });
1687        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1688            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1689        });
1690        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1691            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1692        });
1693
1694        mInjectedCurrentTimeMillis++;
1695
1696        // Package 1 on user-10 comes to foreground.
1697        // Now, also try calling some APIs and make sure foreground apps don't get throttled.
1698        mService.mUidObserver.onUidStateChanged(
1699                UserHandle.getUid(USER_10, CALLING_UID_1),
1700                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
1701        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1702            assertEquals(3, mManager.getRemainingCallCount());
1703            assertFalse(mManager.isRateLimitingActive());
1704
1705            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1706
1707            assertEquals(2, mManager.getRemainingCallCount());
1708            assertFalse(mManager.isRateLimitingActive());
1709
1710            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1711
1712            assertEquals(1, mManager.getRemainingCallCount());
1713            assertFalse(mManager.isRateLimitingActive());
1714
1715            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1716
1717            assertEquals(0, mManager.getRemainingCallCount());
1718            assertTrue(mManager.isRateLimitingActive());
1719        });
1720        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1721            assertEquals(3, mManager.getRemainingCallCount());
1722
1723            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1724            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1725            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1726
1727            assertEquals(0, mManager.getRemainingCallCount());
1728            assertTrue(mManager.isRateLimitingActive());
1729        });
1730        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1731            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1732
1733            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1734            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1735            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1736
1737            assertEquals(0, mManager.getRemainingCallCount());
1738            assertTrue(mManager.isRateLimitingActive());
1739        });
1740        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1741            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1742
1743            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1744            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1745            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1746
1747            assertEquals(0, mManager.getRemainingCallCount());
1748            assertTrue(mManager.isRateLimitingActive());
1749        });
1750        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1751            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1752
1753            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1754            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1755            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1756
1757            assertEquals(0, mManager.getRemainingCallCount());
1758            assertTrue(mManager.isRateLimitingActive());
1759        });
1760        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1761            assertEquals(3, mManager.getRemainingCallCount());
1762
1763            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1764            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1765            mManager.setDynamicShortcuts(list(makeShortcut("s")));
1766
1767            assertEquals(3, mManager.getRemainingCallCount()); // Still 3!
1768            assertFalse(mManager.isRateLimitingActive());
1769        });
1770    }
1771
1772
1773    public void testThrottling_resetByInternalCall() throws Exception {
1774        prepareCrossProfileDataSet();
1775
1776        dumpsysOnLogcat("Before save & load");
1777
1778        mService.saveDirtyInfo();
1779        initService();
1780
1781        // First, all packages have less than 3 (== initial value) remaining calls.
1782
1783        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1784            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1785        });
1786        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1787            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1788        });
1789        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1790            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1791        });
1792        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1793            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1794        });
1795        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1796            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1797        });
1798        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1799            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1800        });
1801
1802        // Simulate a call from sys UI.
1803        mCallerPermissions.add(permission.RESET_SHORTCUT_MANAGER_THROTTLING);
1804        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_0);
1805
1806        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1807            assertEquals(3, mManager.getRemainingCallCount());
1808        });
1809        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1810            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1811        });
1812        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1813            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1814        });
1815        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1816            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1817        });
1818        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1819            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1820        });
1821        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1822            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1823        });
1824
1825        mManager.onApplicationActive(CALLING_PACKAGE_3, USER_0);
1826
1827        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1828            assertEquals(3, mManager.getRemainingCallCount());
1829        });
1830        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1831            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1832        });
1833        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1834            assertEquals(3, mManager.getRemainingCallCount());
1835        });
1836        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1837            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1838        });
1839        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1840            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1841        });
1842        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1843            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1844        });
1845
1846        mManager.onApplicationActive(CALLING_PACKAGE_1, USER_10);
1847
1848        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
1849            assertEquals(3, mManager.getRemainingCallCount());
1850        });
1851        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
1852            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1853        });
1854        runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
1855            assertEquals(3, mManager.getRemainingCallCount());
1856        });
1857        runWithCaller(CALLING_PACKAGE_4, USER_0, () -> {
1858            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1859        });
1860        runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
1861            MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
1862        });
1863        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1864            assertEquals(3, mManager.getRemainingCallCount());
1865        });
1866    }
1867
1868    public void testReportShortcutUsed() {
1869        mRunningUsers.put(USER_10, true);
1870
1871        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
1872            reset(mMockUsageStatsManagerInternal);
1873
1874            // Report with an nonexistent shortcut.
1875            mManager.reportShortcutUsed("s1");
1876            verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
1877                    anyString(), anyString(), anyInt());
1878
1879            // Publish s2, but s1 still doesn't exist.
1880            mManager.setDynamicShortcuts(list(makeShortcut("s2")));
1881            mManager.reportShortcutUsed("s1");
1882            verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
1883                    anyString(), anyString(), anyInt());
1884
1885            mManager.reportShortcutUsed("s2");
1886            verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
1887                    eq(CALLING_PACKAGE_1), eq("s2"), eq(USER_10));
1888
1889        });
1890        runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
1891            // Try with a different package.
1892            reset(mMockUsageStatsManagerInternal);
1893
1894            // Report with an nonexistent shortcut.
1895            mManager.reportShortcutUsed("s2");
1896            verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
1897                    anyString(), anyString(), anyInt());
1898
1899            // Publish s2, but s1 still doesn't exist.
1900            mManager.setDynamicShortcuts(list(makeShortcut("s3")));
1901            mManager.reportShortcutUsed("s2");
1902            verify(mMockUsageStatsManagerInternal, times(0)).reportShortcutUsage(
1903                    anyString(), anyString(), anyInt());
1904
1905            mManager.reportShortcutUsed("s3");
1906            verify(mMockUsageStatsManagerInternal, times(1)).reportShortcutUsage(
1907                    eq(CALLING_PACKAGE_2), eq("s3"), eq(USER_10));
1908
1909        });
1910    }
1911
1912    // Test for a ShortcutInfo method.
1913    public void testGetResourcePackageName() {
1914        assertEquals(null, ShortcutInfo.getResourcePackageName(""));
1915        assertEquals(null, ShortcutInfo.getResourcePackageName("abc"));
1916        assertEquals("p", ShortcutInfo.getResourcePackageName("p:"));
1917        assertEquals("p", ShortcutInfo.getResourcePackageName("p:xx"));
1918        assertEquals("pac", ShortcutInfo.getResourcePackageName("pac:"));
1919    }
1920
1921    // Test for a ShortcutInfo method.
1922    public void testGetResourceTypeName() {
1923        assertEquals(null, ShortcutInfo.getResourceTypeName(""));
1924        assertEquals(null, ShortcutInfo.getResourceTypeName(":"));
1925        assertEquals(null, ShortcutInfo.getResourceTypeName("/"));
1926        assertEquals(null, ShortcutInfo.getResourceTypeName("/:"));
1927        assertEquals("a", ShortcutInfo.getResourceTypeName(":a/"));
1928        assertEquals("type", ShortcutInfo.getResourceTypeName("xxx:type/yyy"));
1929    }
1930
1931    // Test for a ShortcutInfo method.
1932    public void testGetResourceTypeAndEntryName() {
1933        assertEquals(null, ShortcutInfo.getResourceTypeAndEntryName(""));
1934        assertEquals(null, ShortcutInfo.getResourceTypeAndEntryName("abc"));
1935        assertEquals("", ShortcutInfo.getResourceTypeAndEntryName("p:"));
1936        assertEquals("x", ShortcutInfo.getResourceTypeAndEntryName(":x"));
1937        assertEquals("x", ShortcutInfo.getResourceTypeAndEntryName("p:x"));
1938        assertEquals("xyz", ShortcutInfo.getResourceTypeAndEntryName("pac:xyz"));
1939    }
1940
1941    // Test for a ShortcutInfo method.
1942    public void testGetResourceEntryName() {
1943        assertEquals(null, ShortcutInfo.getResourceEntryName(""));
1944        assertEquals(null, ShortcutInfo.getResourceEntryName("ab:"));
1945        assertEquals("", ShortcutInfo.getResourceEntryName("/"));
1946        assertEquals("abc", ShortcutInfo.getResourceEntryName("/abc"));
1947        assertEquals("abc", ShortcutInfo.getResourceEntryName("xyz/abc"));
1948    }
1949
1950    // Test for a ShortcutInfo method.
1951    public void testLookUpResourceName_systemResources() {
1952        // For android system resources, lookUpResourceName will simply return the value as a
1953        // string, regardless of "withType".
1954        final Resources res = getTestContext().getResources();
1955
1956        assertEquals("" + android.R.string.cancel, ShortcutInfo.lookUpResourceName(res,
1957                android.R.string.cancel, true, getTestContext().getPackageName()));
1958        assertEquals("" + android.R.drawable.alert_dark_frame, ShortcutInfo.lookUpResourceName(res,
1959                android.R.drawable.alert_dark_frame, true, getTestContext().getPackageName()));
1960        assertEquals("" + android.R.string.cancel, ShortcutInfo.lookUpResourceName(res,
1961                android.R.string.cancel, false, getTestContext().getPackageName()));
1962    }
1963
1964    public void testLookUpResourceName_appResources() {
1965        final Resources res = getTestContext().getResources();
1966
1967        assertEquals("shortcut_text1", ShortcutInfo.lookUpResourceName(res,
1968                R.string.shortcut_text1, false, getTestContext().getPackageName()));
1969        assertEquals("string/shortcut_text1", ShortcutInfo.lookUpResourceName(res,
1970                R.string.shortcut_text1, true, getTestContext().getPackageName()));
1971
1972        assertEquals("black_16x64", ShortcutInfo.lookUpResourceName(res,
1973                R.drawable.black_16x64, false, getTestContext().getPackageName()));
1974        assertEquals("drawable/black_16x64", ShortcutInfo.lookUpResourceName(res,
1975                R.drawable.black_16x64, true, getTestContext().getPackageName()));
1976    }
1977
1978    // Test for a ShortcutInfo method.
1979    public void testLookUpResourceId_systemResources() {
1980        final Resources res = getTestContext().getResources();
1981
1982        assertEquals(android.R.string.cancel, ShortcutInfo.lookUpResourceId(res,
1983                "" + android.R.string.cancel, null,
1984                getTestContext().getPackageName()));
1985        assertEquals(android.R.drawable.alert_dark_frame, ShortcutInfo.lookUpResourceId(res,
1986                "" + android.R.drawable.alert_dark_frame, null,
1987                getTestContext().getPackageName()));
1988    }
1989
1990    // Test for a ShortcutInfo method.
1991    public void testLookUpResourceId_appResources() {
1992        final Resources res = getTestContext().getResources();
1993
1994        assertEquals(R.string.shortcut_text1,
1995                ShortcutInfo.lookUpResourceId(res, "shortcut_text1", "string",
1996                        getTestContext().getPackageName()));
1997
1998        assertEquals(R.string.shortcut_text1,
1999                ShortcutInfo.lookUpResourceId(res, "string/shortcut_text1", null,
2000                        getTestContext().getPackageName()));
2001
2002        assertEquals(R.drawable.black_16x64,
2003                ShortcutInfo.lookUpResourceId(res, "black_16x64", "drawable",
2004                        getTestContext().getPackageName()));
2005
2006        assertEquals(R.drawable.black_16x64,
2007                ShortcutInfo.lookUpResourceId(res, "drawable/black_16x64", null,
2008                        getTestContext().getPackageName()));
2009    }
2010
2011    public void testDumpCheckin() throws IOException {
2012        prepareCrossProfileDataSet();
2013
2014        // prepareCrossProfileDataSet() doesn't set any icons, so do set here.
2015        final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32);
2016        final Icon res64x64 = Icon.createWithResource(getTestContext(), R.drawable.black_64x64);
2017        final Icon bmp32x32 = Icon.createWithBitmap(BitmapFactory.decodeResource(
2018                getTestContext().getResources(), R.drawable.black_32x32));
2019        final Icon bmp64x64 = Icon.createWithBitmap(BitmapFactory.decodeResource(
2020                getTestContext().getResources(), R.drawable.black_64x64));
2021
2022        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
2023            assertTrue(mManager.setDynamicShortcuts(list(
2024                    makeShortcutWithIcon("res32x32", res32x32),
2025                    makeShortcutWithIcon("res64x64", res64x64),
2026                    makeShortcutWithIcon("bmp32x32", bmp32x32),
2027                    makeShortcutWithIcon("bmp64x64", bmp64x64))));
2028        });
2029
2030        // We can't predict the compressed bitmap sizes, so get the real sizes here.
2031        final long bitmapTotal =
2032                new File(getBitmapAbsPath(USER_0, CALLING_PACKAGE_2, "bmp32x32")).length() +
2033                new File(getBitmapAbsPath(USER_0, CALLING_PACKAGE_2, "bmp64x64")).length();
2034
2035        // Read the expected output and inject the bitmap size.
2036        final String expected = readTestAsset("shortcut/dumpsys_expected.txt")
2037                .replace("***BITMAP_SIZE***", String.valueOf(bitmapTotal));
2038
2039        assertEquals(expected, dumpCheckin());
2040    }
2041
2042    /**
2043     * Make sure the legacy file format that only supported a single intent per shortcut
2044     * can still be read.
2045     */
2046    public void testLoadLegacySavedFile() throws Exception {
2047        final File path = mService.getUserFile(USER_0);
2048        path.getParentFile().mkdirs();
2049        try (Writer w = new FileWriter(path)) {
2050            w.write(readTestAsset("shortcut/shortcut_legacy_file.xml"));
2051        };
2052        initService();
2053        mService.handleUnlockUser(USER_0);
2054
2055        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
2056            assertWith(getCallerShortcuts())
2057                    .haveIds("manifest-shortcut-storage")
2058                    .forShortcutWithId("manifest-shortcut-storage", si -> {
2059                        assertEquals("android.settings.INTERNAL_STORAGE_SETTINGS",
2060                                si.getIntent().getAction());
2061                        assertEquals(12345, si.getIntent().getIntExtra("key", 0));
2062                    });
2063        });
2064    }
2065
2066    public void testIsUserUnlocked() {
2067        mRunningUsers.clear();
2068        mUnlockedUsers.clear();
2069
2070        assertFalse(mService.isUserUnlockedL(USER_0));
2071        assertFalse(mService.isUserUnlockedL(USER_10));
2072
2073        // Start user 0, still locked.
2074        mRunningUsers.put(USER_0, true);
2075        assertFalse(mService.isUserUnlockedL(USER_0));
2076        assertFalse(mService.isUserUnlockedL(USER_10));
2077
2078        // Unlock user.
2079        mUnlockedUsers.put(USER_0, true);
2080        assertTrue(mService.isUserUnlockedL(USER_0));
2081        assertFalse(mService.isUserUnlockedL(USER_10));
2082
2083        // Clear again.
2084        mRunningUsers.clear();
2085        mUnlockedUsers.clear();
2086
2087        // Directly call the lifecycle event.  Now also locked.
2088        mService.handleUnlockUser(USER_0);
2089        assertTrue(mService.isUserUnlockedL(USER_0));
2090        assertFalse(mService.isUserUnlockedL(USER_10));
2091
2092        // Directly call the stop lifecycle event.  Goes back to the initial state.
2093        mService.handleStopUser(USER_0);
2094        assertFalse(mService.isUserUnlockedL(USER_0));
2095        assertFalse(mService.isUserUnlockedL(USER_10));
2096    }
2097
2098    public void testEphemeralApp() {
2099        mRunningUsers.put(USER_10, true); // this test needs user 10.
2100
2101        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
2102            assertWith(mManager.getDynamicShortcuts()).isEmpty();
2103        });
2104        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
2105            assertWith(mManager.getDynamicShortcuts()).isEmpty();
2106        });
2107        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
2108            assertWith(mManager.getDynamicShortcuts()).isEmpty();
2109        });
2110        // Make package 1 ephemeral.
2111        mEphemeralPackages.add(PackageWithUser.of(USER_0, CALLING_PACKAGE_1));
2112
2113        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
2114            assertExpectException(IllegalStateException.class, "Ephemeral apps", () -> {
2115                mManager.getDynamicShortcuts();
2116            });
2117        });
2118        runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
2119            assertWith(mManager.getDynamicShortcuts()).isEmpty();
2120        });
2121        runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
2122            assertWith(mManager.getDynamicShortcuts()).isEmpty();
2123        });
2124    }
2125}
2126