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