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