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