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  */
16 package android.content.pm.cts.shortcutmanager;
17 
18 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.*;
19 
20 import android.app.Activity;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.ContextWrapper;
24 import android.content.Intent;
25 import android.content.LocusId;
26 import android.content.pm.LauncherApps;
27 import android.content.pm.LauncherApps.ShortcutQuery;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ShortcutInfo;
30 import android.content.pm.ShortcutManager;
31 import android.content.res.Resources;
32 import android.graphics.drawable.AdaptiveIconDrawable;
33 import android.graphics.drawable.Drawable;
34 import android.graphics.drawable.Icon;
35 import android.os.Bundle;
36 import android.os.PersistableBundle;
37 import android.os.StrictMode;
38 import android.os.StrictMode.ThreadPolicy;
39 import android.os.UserHandle;
40 import androidx.annotation.NonNull;
41 import android.test.InstrumentationTestCase;
42 import android.text.TextUtils;
43 
44 import java.util.ArrayList;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.concurrent.atomic.AtomicReference;
49 
50 public abstract class ShortcutManagerCtsTestsBase extends InstrumentationTestCase {
51     protected static final String TAG = "ShortcutCTS";
52 
53     private static final boolean DUMPSYS_IN_TEARDOWN = false; // DO NOT SUBMIT WITH true
54 
55     /**
56      * Whether to enable strict mode or not.
57      *
58      * TODO Enable it after fixing b/68051728. Somehow violations would happen on the dashboard
59      * only and can't reproduce it locally.
60      */
61     private static final boolean ENABLE_STRICT_MODE = false;
62 
63     private static class SpoofingContext extends ContextWrapper {
64         private final String mPackageName;
65 
SpoofingContext(Context base, String packageName)66         public SpoofingContext(Context base, String packageName) {
67             super(base);
68             mPackageName = packageName;
69         }
70 
71         @Override
getPackageName()72         public String getPackageName() {
73             return mPackageName;
74         }
75     }
76 
77     private Context mCurrentCallerPackage;
78     private int mUserId;
79     private UserHandle mUserHandle;
80 
81     private String mOriginalLauncher;
82 
83     protected Context mPackageContext1;
84     protected Context mPackageContext2;
85     protected Context mPackageContext3;
86     protected Context mPackageContext4;
87 
88     protected Context mLauncherContext1;
89     protected Context mLauncherContext2;
90     protected Context mLauncherContext3;
91     protected Context mLauncherContext4;
92 
93     private LauncherApps mLauncherApps1;
94     private LauncherApps mLauncherApps2;
95     private LauncherApps mLauncherApps3;
96     private LauncherApps mLauncherApps4;
97 
98     private Map<Context, ShortcutManager> mManagers = new HashMap<>();
99     private Map<Context, LauncherApps> mLauncherAppses = new HashMap<>();
100 
101     private ShortcutManager mCurrentManager;
102     private LauncherApps mCurrentLauncherApps;
103 
104     private static final String[] ACTIVITIES_WITH_MANIFEST_SHORTCUTS = {
105             "Launcher_manifest_1",
106             "Launcher_manifest_2",
107             "Launcher_manifest_3",
108             "Launcher_manifest_4a",
109             "Launcher_manifest_4b",
110             "Launcher_manifest_error_1",
111             "Launcher_manifest_error_2",
112             "Launcher_manifest_error_3"
113     };
114 
115     private ComponentName mTargetActivityOverride;
116 
117     private static class ShortcutActivity extends Activity {
118     }
119 
120     @Override
setUp()121     protected void setUp() throws Exception {
122         super.setUp();
123 
124         mUserId = getTestContext().getUserId();
125         mUserHandle = android.os.Process.myUserHandle();
126 
127         resetConfig(getInstrumentation());
128         final String config = getOverrideConfig();
129         if (config != null) {
130             overrideConfig(getInstrumentation(), config);
131         }
132         mOriginalLauncher = getDefaultLauncher(getInstrumentation());
133 
134         mPackageContext1 = new SpoofingContext(getTestContext(),
135                 "android.content.pm.cts.shortcutmanager.packages.package1");
136         mPackageContext2 = new SpoofingContext(getTestContext(),
137                 "android.content.pm.cts.shortcutmanager.packages.package2");
138         mPackageContext3 = new SpoofingContext(getTestContext(),
139                 "android.content.pm.cts.shortcutmanager.packages.package3");
140         mPackageContext4 = new SpoofingContext(getTestContext(),
141                 "android.content.pm.cts.shortcutmanager.packages.package4");
142         mLauncherContext1 = new SpoofingContext(getTestContext(),
143                 "android.content.pm.cts.shortcutmanager.packages.launcher1");
144         mLauncherContext2 = new SpoofingContext(getTestContext(),
145                 "android.content.pm.cts.shortcutmanager.packages.launcher2");
146         mLauncherContext3 = new SpoofingContext(getTestContext(),
147                 "android.content.pm.cts.shortcutmanager.packages.launcher3");
148         mLauncherContext4 = new SpoofingContext(getTestContext(),
149                 "android.content.pm.cts.shortcutmanager.packages.launcher4");
150 
151         mLauncherApps1 = new LauncherApps(mLauncherContext1);
152         mLauncherApps2 = new LauncherApps(mLauncherContext2);
153         mLauncherApps3 = new LauncherApps(mLauncherContext3);
154         mLauncherApps4 = new LauncherApps(mLauncherContext4);
155 
156         clearShortcuts(getInstrumentation(), mUserId, mPackageContext1.getPackageName());
157         clearShortcuts(getInstrumentation(), mUserId, mPackageContext2.getPackageName());
158         clearShortcuts(getInstrumentation(), mUserId, mPackageContext3.getPackageName());
159         clearShortcuts(getInstrumentation(), mUserId, mPackageContext4.getPackageName());
160 
161         setCurrentCaller(mPackageContext1);
162 
163         // Make sure shortcuts are removed.
164         withCallers(getAllPublishers(), () -> {
165             // Clear all shortcuts.
166             clearShortcuts(getInstrumentation(), mUserId, getCurrentCallingPackage());
167 
168             disableActivitiesWithManifestShortucts();
169 
170             assertEquals("for " + getCurrentCallingPackage(),
171                     0, getManager().getDynamicShortcuts().size());
172             assertEquals("for " + getCurrentCallingPackage(),
173                     0, getManager().getPinnedShortcuts().size());
174             assertEquals("for " + getCurrentCallingPackage(),
175                     0, getManager().getManifestShortcuts().size());
176         });
177     }
178 
179     @Override
tearDown()180     protected void tearDown() throws Exception {
181         if (DUMPSYS_IN_TEARDOWN) {
182             dumpsysShortcut(getInstrumentation());
183         }
184 
185         withCallers(getAllPublishers(), () -> disableActivitiesWithManifestShortucts());
186 
187         resetConfig(getInstrumentation());
188 
189         if (!TextUtils.isEmpty(mOriginalLauncher)) {
190             setDefaultLauncher(getInstrumentation(), mOriginalLauncher);
191         }
192 
193         super.tearDown();
194     }
195 
getTestContext()196     protected Context getTestContext() {
197         return getInstrumentation().getContext();
198     }
199 
getUserHandle()200     protected UserHandle getUserHandle() {
201         return mUserHandle;
202     }
203 
getAllPublishers()204     protected List<Context> getAllPublishers() {
205         // 4 has a different signature, so we can't call for it.
206         return list(mPackageContext1, mPackageContext2, mPackageContext3);
207     }
208 
getAllLaunchers()209     protected List<Context> getAllLaunchers() {
210         // 4 has a different signature, so we can't call for it.
211         return list(mLauncherContext1, mLauncherContext2, mLauncherContext3);
212     }
213 
getAllCallers()214     protected List<Context> getAllCallers() {
215         return list(
216                 mPackageContext1, mPackageContext2, mPackageContext3, mPackageContext4,
217                 mLauncherContext1, mLauncherContext2, mLauncherContext3, mLauncherContext4);
218     }
219 
getActivity(String className)220     protected ComponentName getActivity(String className) {
221         return new ComponentName(getCurrentCallingPackage(),
222                 "android.content.pm.cts.shortcutmanager.packages." + className);
223 
224     }
225 
disableActivitiesWithManifestShortucts()226     protected void disableActivitiesWithManifestShortucts() {
227         if (getManager().getManifestShortcuts().size() > 0) {
228             // Disable DISABLED_ACTIVITIES
229             for (String className : ACTIVITIES_WITH_MANIFEST_SHORTCUTS) {
230                 enableManifestActivity(className, false);
231             }
232         }
233     }
234 
enableManifestActivity(String className, boolean enabled)235     protected void enableManifestActivity(String className, boolean enabled) {
236         getTestContext().getPackageManager().setComponentEnabledSetting(getActivity(className),
237                 enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
238                         : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
239                 PackageManager.DONT_KILL_APP);
240     }
241 
setTargetActivityOverride(String className)242     protected void setTargetActivityOverride(String className) {
243         mTargetActivityOverride = getActivity(className);
244     }
245 
246 
withCallers(List<Context> callers, Runnable r)247     protected void withCallers(List<Context> callers, Runnable r) {
248         for (Context c : callers) {
249             runWithCaller(c, r);
250         }
251     }
252 
getOverrideConfig()253     protected String getOverrideConfig() {
254         return null;
255     }
256 
setCurrentCaller(Context callerContext)257     protected void setCurrentCaller(Context callerContext) {
258         mCurrentCallerPackage = callerContext;
259 
260         if (!mManagers.containsKey(mCurrentCallerPackage)) {
261             mManagers.put(mCurrentCallerPackage, new ShortcutManager(mCurrentCallerPackage));
262         }
263         mCurrentManager = mManagers.get(mCurrentCallerPackage);
264 
265         if (!mLauncherAppses.containsKey(mCurrentCallerPackage)) {
266             mLauncherAppses.put(mCurrentCallerPackage, new LauncherApps(mCurrentCallerPackage));
267         }
268         mCurrentLauncherApps = mLauncherAppses.get(mCurrentCallerPackage);
269 
270         mTargetActivityOverride = null;
271     }
272 
getCurrentCallerContext()273     protected Context getCurrentCallerContext() {
274         return mCurrentCallerPackage;
275     }
276 
getCurrentCallingPackage()277     protected String getCurrentCallingPackage() {
278         return getCurrentCallerContext().getPackageName();
279     }
280 
getManager()281     protected ShortcutManager getManager() {
282         return mCurrentManager;
283     }
284 
getLauncherApps()285     protected LauncherApps getLauncherApps() {
286         return mCurrentLauncherApps;
287     }
288 
runWithStrictMode(Runnable r)289     protected void runWithStrictMode(Runnable r) {
290         final ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
291         try {
292             if (ENABLE_STRICT_MODE) {
293                 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
294                         .detectAll()
295                         .penaltyDeath()
296                         .build());
297             }
298             r.run();
299         } finally {
300             StrictMode.setThreadPolicy(oldPolicy);
301         }
302     }
303 
runWithNoStrictMode(Runnable r)304     protected void runWithNoStrictMode(Runnable r) {
305         final ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
306         try {
307             StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
308                     .permitAll()
309                     .build());
310             r.run();
311         } finally {
312             StrictMode.setThreadPolicy(oldPolicy);
313         }
314     }
315 
runWithCaller(Context callerContext, Runnable r)316     protected void runWithCaller(Context callerContext, Runnable r) {
317         final Context prev = mCurrentCallerPackage;
318 
319         setCurrentCaller(callerContext);
320 
321         r.run();
322 
323         setCurrentCaller(prev);
324     }
325 
runWithCallerWithStrictMode(Context callerContext, Runnable r)326     protected void runWithCallerWithStrictMode(Context callerContext, Runnable r) {
327         runWithCaller(callerContext, () -> runWithStrictMode(r));
328     }
329 
runWithCallerWithNoStrictMode(Context callerContext, Runnable r)330     protected void runWithCallerWithNoStrictMode(Context callerContext, Runnable r) {
331         runWithCaller(callerContext, () -> runWithNoStrictMode(r));
332     }
333 
makeBundle(Object... keysAndValues)334     public static Bundle makeBundle(Object... keysAndValues) {
335         assertTrue((keysAndValues.length % 2) == 0);
336 
337         if (keysAndValues.length == 0) {
338             return null;
339         }
340         final Bundle ret = new Bundle();
341 
342         for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
343             final String key = keysAndValues[i].toString();
344             final Object value = keysAndValues[i + 1];
345 
346             if (value == null) {
347                 ret.putString(key, null);
348             } else if (value instanceof Integer) {
349                 ret.putInt(key, (Integer) value);
350             } else if (value instanceof String) {
351                 ret.putString(key, (String) value);
352             } else if (value instanceof Bundle) {
353                 ret.putBundle(key, (Bundle) value);
354             } else {
355                 fail("Type not supported yet: " + value.getClass().getName());
356             }
357         }
358         return ret;
359     }
360 
makePersistableBundle(Object... keysAndValues)361     public static PersistableBundle makePersistableBundle(Object... keysAndValues) {
362         assertTrue((keysAndValues.length % 2) == 0);
363 
364         if (keysAndValues.length == 0) {
365             return null;
366         }
367         final PersistableBundle ret = new PersistableBundle();
368 
369         for (int i = keysAndValues.length - 2; i >= 0; i -= 2) {
370             final String key = keysAndValues[i].toString();
371             final Object value = keysAndValues[i + 1];
372 
373             if (value == null) {
374                 ret.putString(key, null);
375             } else if (value instanceof Integer) {
376                 ret.putInt(key, (Integer) value);
377             } else if (value instanceof String) {
378                 ret.putString(key, (String) value);
379             } else if (value instanceof PersistableBundle) {
380                 ret.putPersistableBundle(key, (PersistableBundle) value);
381             } else {
382                 fail("Type not supported yet: " + value.getClass().getName());
383             }
384         }
385         return ret;
386     }
387 
388     /**
389      * Make a shortcut with an ID.
390      */
makeShortcut(String id)391     protected ShortcutInfo makeShortcut(String id) {
392         return makeShortcut(id, "Title-" + id);
393     }
394 
395     /**
396      * Make a shortcut with an ID and explicit rank.
397      */
makeShortcutWithRank(String id, int rank)398     protected ShortcutInfo makeShortcutWithRank(String id, int rank) {
399         return makeShortcut(
400                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
401                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), rank, /* locusId =*/ null,
402                 /* longLived =*/ false);
403     }
404 
405     /**
406      * Make a shortcut with an ID and a locus ID.
407      */
makeShortcutWithLocusId(String id, String locusId)408     protected ShortcutInfo makeShortcutWithLocusId(String id, String locusId) {
409         return makeShortcut(
410                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
411                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
412                 new LocusId(locusId), /* longLived =*/ false);
413     }
414 
415     /**
416      * Make a shortcut with an ID and a title.
417      */
makeShortcut(String id, String shortLabel)418     protected ShortcutInfo makeShortcut(String id, String shortLabel) {
419         return makeShortcut(
420                 id, shortLabel, /* activity =*/ null, /* icon =*/ null,
421                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
422                 /* locusId =*/ null, /* longLived =*/ false);
423     }
424 
makeShortcut(String id, ComponentName activity)425     protected ShortcutInfo makeShortcut(String id, ComponentName activity) {
426         return makeShortcut(
427                 id, "Title-" + id, activity, /* icon =*/ null,
428                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
429                 /* locusId =*/ null, /* longLived =*/ false);
430     }
431 
432     /**
433      * Make a shortcut with an ID and icon.
434      */
makeShortcutWithIcon(String id, Icon icon)435     protected ShortcutInfo makeShortcutWithIcon(String id, Icon icon) {
436         return makeShortcut(
437                 id, "Title-" + id, /* activity =*/ null, icon,
438                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
439                 /* locusId =*/ null, /* longLived =*/ false);
440     }
441 
442     /**
443      * Make a long-lived shortcut with an ID.
444      */
makeLongLivedShortcut(String id)445     protected ShortcutInfo makeLongLivedShortcut(String id) {
446         return makeShortcut(
447                 id, "Title-" + id, /* activity =*/ null, /* icon =*/ null,
448                 makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0,
449                 /* locusId =*/ null, /* longLived =*/ true);
450     }
451 
452     /**
453      * Make multiple shortcuts with IDs.
454      */
makeShortcuts(String... ids)455     protected List<ShortcutInfo> makeShortcuts(String... ids) {
456         final ArrayList<ShortcutInfo> ret = new ArrayList();
457         for (String id : ids) {
458             ret.add(makeShortcut(id));
459         }
460         return ret;
461     }
462 
463     /**
464      * Makes an array of shortcut IDs.
465      * For example, makeIds("sX", 4, 9) will return {"sX4", "sX5", "sX6", "sX7", "sX8", "sX9"}.
466      */
makeIds(String prefix, int first, int last)467     protected String[] makeIds(String prefix, int first, int last) {
468         final int len = last - first + 1;
469         final String[] ret = new String[len];
470         for (int i = 0; i < len; i++) {
471             ret[i] = prefix + (first + i);
472         }
473         return ret;
474     }
475 
makeShortcutBuilder(String id)476     protected ShortcutInfo.Builder makeShortcutBuilder(String id) {
477         return new ShortcutInfo.Builder(getCurrentCallerContext(), id);
478     }
479 
480     /**
481      * Make a shortcut with details.
482      */
makeShortcut(String id, String shortLabel, ComponentName activity, Icon icon, Intent intent, int rank, LocusId locusId, boolean longLived)483     protected ShortcutInfo makeShortcut(String id, String shortLabel, ComponentName activity,
484             Icon icon, Intent intent, int rank, LocusId locusId, boolean longLived) {
485         final ShortcutInfo.Builder b = makeShortcutBuilder(id)
486                 .setShortLabel(shortLabel)
487                 .setRank(rank)
488                 .setIntent(intent)
489                 .setLongLived(longLived);
490         if (activity != null) {
491             b.setActivity(activity);
492         } else if (mTargetActivityOverride != null) {
493             b.setActivity(mTargetActivityOverride);
494         }
495         if (icon != null) {
496             b.setIcon(icon);
497         }
498         if (locusId != null) {
499             b.setLocusId(locusId);
500         }
501         return b.build();
502     }
503 
504     /**
505      * Make an intent.
506      */
makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues)507     protected Intent makeIntent(String action, Class<?> clazz, Object... bundleKeysAndValues) {
508         final Intent intent = new Intent(action);
509         intent.setComponent(makeComponent(clazz));
510         intent.replaceExtras(makeBundle(bundleKeysAndValues));
511         return intent;
512     }
513 
514     /**
515      * Make an component name, with the client context.
516      */
517     @NonNull
makeComponent(Class<?> clazz)518     protected ComponentName makeComponent(Class<?> clazz) {
519         return new ComponentName(getCurrentCallerContext(), clazz);
520     }
521 
getIconAsLauncher(Context launcherContext, String packageName, String shortcutId)522     protected Drawable getIconAsLauncher(Context launcherContext, String packageName,
523             String shortcutId) {
524         return getIconAsLauncher(launcherContext, packageName, shortcutId, /* withBadge=*/ true);
525     }
526 
getIconAsLauncher(Context launcherContext, String packageName, String shortcutId, boolean withBadge)527     protected Drawable getIconAsLauncher(Context launcherContext, String packageName,
528             String shortcutId, boolean withBadge) {
529         runWithNoStrictMode(() -> setDefaultLauncher(getInstrumentation(), launcherContext));
530 
531         final AtomicReference<Drawable> ret = new AtomicReference<>();
532 
533         runWithCallerWithNoStrictMode(launcherContext, () -> {
534             final ShortcutQuery q = new ShortcutQuery()
535                     .setQueryFlags(ShortcutQuery.FLAG_MATCH_DYNAMIC
536                                     | ShortcutQuery.FLAG_MATCH_MANIFEST
537                                     | ShortcutQuery.FLAG_MATCH_PINNED
538                                     | ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY)
539                     .setPackage(packageName)
540                     .setShortcutIds(list(shortcutId));
541             final List<ShortcutInfo> found = getLauncherApps().getShortcuts(q, getUserHandle());
542 
543             assertEquals("Shortcut not found", 1, found.size());
544 
545             if (withBadge) {
546                 ret.set(getLauncherApps().getShortcutBadgedIconDrawable(found.get(0), 0));
547             } else {
548                 ret.set(getLauncherApps().getShortcutIconDrawable(found.get(0), 0));
549             }
550         });
551         return ret.get();
552     }
553 
assertIconDimensions(Context launcherContext, String packageName, String shortcutId, Icon expectedIcon)554     protected void assertIconDimensions(Context launcherContext, String packageName,
555             String shortcutId, Icon expectedIcon) {
556         final Drawable actual = getIconAsLauncher(launcherContext, packageName, shortcutId);
557         if (actual == null && expectedIcon == null) {
558             return; // okay
559         }
560         final Drawable expected = expectedIcon.loadDrawable(getTestContext());
561         assertEquals(expected.getIntrinsicWidth(), actual.getIntrinsicWidth());
562         assertEquals(expected.getIntrinsicHeight(), actual.getIntrinsicHeight());
563     }
564 
assertIconDimensions(Icon expectedIcon, Drawable actual)565     protected void assertIconDimensions(Icon expectedIcon, Drawable actual) {
566         if (actual == null && expectedIcon == null) {
567             return; // okay
568         }
569         final Drawable expected = expectedIcon.loadDrawable(getTestContext());
570 
571         if (expected instanceof AdaptiveIconDrawable) {
572             assertTrue(actual instanceof AdaptiveIconDrawable);
573         }
574         assertEquals(expected.getIntrinsicWidth(), actual.getIntrinsicWidth());
575         assertEquals(expected.getIntrinsicHeight(), actual.getIntrinsicHeight());
576     }
577 
loadPackageDrawableIcon(Context packageContext, String resName)578     protected Icon loadPackageDrawableIcon(Context packageContext, String resName)
579             throws Exception {
580         final Resources res = getTestContext().getPackageManager().getResourcesForApplication(
581                 packageContext.getPackageName());
582 
583         // Note the resource package names don't have the numbers.
584         final int id = res.getIdentifier(resName, "drawable",
585                 "android.content.pm.cts.shortcutmanager.packages");
586         if (id == 0) {
587             fail("Drawable " + resName + " is not found in package "
588                     + packageContext.getPackageName());
589         }
590         return Icon.createWithResource(packageContext, id);
591     }
592 
loadCallerDrawableIcon(String resName)593     protected Icon loadCallerDrawableIcon(String resName) throws Exception {
594         return loadPackageDrawableIcon(getCurrentCallerContext(), resName);
595     }
596 
getShortcutsAsLauncher(int flags, String packageName)597     protected List<ShortcutInfo> getShortcutsAsLauncher(int flags, String packageName) {
598         return getShortcutsAsLauncher(flags, packageName, null, 0, null, null);
599     }
600 
getShortcutsAsLauncher( int flags, String packageName, String activityName, long changedSince, List<String> ids, List<LocusId> locusIds)601     protected List<ShortcutInfo> getShortcutsAsLauncher(
602             int flags, String packageName, String activityName,
603             long changedSince, List<String> ids, List<LocusId> locusIds) {
604         final ShortcutQuery q = new ShortcutQuery();
605         q.setQueryFlags(flags);
606         if (packageName != null) {
607             q.setPackage(packageName);
608             if (activityName != null) {
609                 q.setActivity(new ComponentName(packageName,
610                         "android.content.pm.cts.shortcutmanager.packages." + activityName));
611             }
612         }
613         q.setChangedSince(changedSince);
614         if (ids != null && ids.size() > 0) {
615             q.setShortcutIds(ids);
616         }
617         if (locusIds != null && locusIds.size() > 0) {
618             q.setLocusIds(locusIds);
619         }
620         return getLauncherApps().getShortcuts(q, getUserHandle());
621     }
622 }
623