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